packages feed

duckling (empty) → 0.1.0.0

raw patch · 574 files changed

+101149/−0 lines, 574 filesdep +aesondep +arraydep +attoparsecsetup-changed

Dependencies added: aeson, array, attoparsec, base, bytestring, containers, deepseq, dependent-sum, directory, duckling, extra, filepath, hashable, haskell-src-exts, regex-base, regex-pcre, snap-core, snap-server, tasty, tasty-hunit, text, text-show, time, timezone-olson, timezone-series, unordered-containers

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

Files

+ Duckling/AmountOfMoney/EN/Corpus.hs view
@@ -0,0 +1,113 @@+-- 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.AmountOfMoney.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "$ 10"+             , "10$"+             , "10 dollars"+             , "ten dollars"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "10 cent"+             , "ten pennies"+             , "ten cents"+             , "10 c"+             , "10¢"+             ]+  , examples (AmountOfMoneyValue Dollar 1e4)+             [ "$10K"+             , "10k$"+             , "$10,000"+             ]+  , examples (AmountOfMoneyValue USD 3.14)+             [ "USD3.14"+             , "3.14US$"+             , "US$ 3.14"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20\x20ac"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             , "EUR 20.0"+             , "20€"+             , "20 €ur"+             ]+  , examples (AmountOfMoneyValue Pound 10)+             [ "\x00a3\&10"+             , "ten pounds"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rupees"+             , "20Rs"+             , "Rs20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupees 43"+             , "twenty rupees 43"+             ]+  , examples (AmountOfMoneyValue Dollar 20.43)+             [ "$20 and 43c"+             , "$20 43"+             , "20 dollar 43c"+             , "20 dollars 43 cents"+             , "twenty dollar 43 cents"+             , "20 dollar 43"+             , "twenty dollar and 43"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3.01"+             , "GBP 3.01"+             , "3 GBP 1 cent"+             ]+  , examples (AmountOfMoneyValue Unnamed 42)+             [ "42 bucks"+             , "around 42 bucks"+             , "exactly 42 bucks"+             ]+  , examples (AmountOfMoneyValue KWD 42)+             [ "42 KWD"+             , "42 kuwaiti Dinar"+             ]+  , examples (AmountOfMoneyValue LBP 42)+             [ "42 LBP"+             , "42 Lebanese Pounds"+             ]+  , examples (AmountOfMoneyValue EGP 42)+             [ "42 EGP"+             , "42 egyptianpound"+             ]+  , examples (AmountOfMoneyValue QAR 42)+             [ "42 QAR"+             , "42 qatari riyals"+             ]+  , examples (AmountOfMoneyValue SAR 42)+             [ "42 SAR"+             , "42 Saudiriyal"+             ]+  ]
+ Duckling/AmountOfMoney/EN/Rules.hs view
@@ -0,0 +1,192 @@+-- 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 #-}++module Duckling.AmountOfMoney.EN.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import Duckling.Types++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "pounds?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleOtherPounds :: Rule+ruleOtherPounds = Rule+  { name = "other pounds"+  , pattern =+    [ regex "(egyptian|lebanese) ?pounds?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "egyptian" -> Just . Token AmountOfMoney $ currencyOnly EGP+        "lebanese" -> Just . Token AmountOfMoney $ currencyOnly LBP+        _          -> Nothing+      _ -> Nothing+  }++ruleRiyals :: Rule+ruleRiyals = Rule+  { name = "riyals"+  , pattern =+    [ regex "(qatari|saudi) ?riyals?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "qatari" -> Just . Token AmountOfMoney $ currencyOnly QAR+        "saudi"  -> Just . Token AmountOfMoney $ currencyOnly SAR+        _        -> Nothing+      _ -> Nothing+  }++ruleDinars :: Rule+ruleDinars = Rule+  { name = "dinars"+  , pattern =+    [ regex "(kuwaiti) ?dinars?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "kuwaiti" -> Just . Token AmountOfMoney $ currencyOnly KWD+        _        -> Nothing+      _ -> Nothing+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "dirham"+  , pattern =+    [ regex "dirhams?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cents?|penn(y|ies)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleBucks :: Rule+ruleBucks = Rule+  { name = "bucks"+  , pattern =+    [ regex "bucks?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Unnamed+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "and"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , regex "and"+    , dimension Numeral+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 "exactly|precisely|about|approx(\\.|imately)?|close to|near( to)?|around|almost"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleBucks+  , ruleCent+  , ruleDinars+  , ruleDirham+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleOtherPounds+  , rulePounds+  , rulePrecision+  , ruleRiyals+  ]
+ Duckling/AmountOfMoney/ES/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.ES.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ES}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "diez dollars"+             , "diez dólares"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "nueve pounds"+             , "9 libras"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             , "3 gbp 1 centavo"+             , "3 gbp y 1 centavo"+             ]+  , examples (AmountOfMoneyValue PTS 15)+             [ "15 Pt"+             , "15pta"+             , "15Ptas"+             ]+  ]
+ Duckling/AmountOfMoney/ES/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.ES.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleDollar :: Rule+ruleDollar = Rule+  { name = "dollar"+  , pattern =+    [ regex "d(\x00f3|o)lar(es)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "centavos?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "(pound|libra)s?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "y"+    , dimension Numeral+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "y"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCent+  , ruleDollar+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , rulePounds+  ]
+ Duckling/AmountOfMoney/FR/Corpus.hs view
@@ -0,0 +1,65 @@+-- 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.AmountOfMoney.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "dix dollars"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             , "1 USD et 23 centimes"+             , "1 USD 23 cents"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue Unnamed 3)+             [ "3 balles"+             , "à peu près 3 pouloutes"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "exactement £9"+             , "neuf pounds"+             , "quasi neuf livres"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  ]
+ Duckling/AmountOfMoney/FR/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.FR.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "et"+    , dimension Numeral+    ]+  , 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 "exactement|quasi|plus ou moins|environ|autour de|(a|\x00e0) peu pr(e|\x00e8)s"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cent(ime)?s?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "(livre|pound)s?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "et"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleUnnamedCurrency :: Rule+ruleUnnamedCurrency = Rule+  { name = "unnamed currencyOnly"+  , pattern =+    [ regex "(balle|pouloute)s?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Unnamed+  }++rules :: [Rule]+rules =+  [ ruleCent+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , rulePounds+  , rulePrecision+  , ruleUnnamedCurrency+  ]
+ Duckling/AmountOfMoney/GA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "deich dollair"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "deich ceinteanna"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10,000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue EUR 10000)+             [ "€10,000"+             , "10K€"+             , "€10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1.23"+             ]+  , examples (AmountOfMoneyValue Dollar 2.23)+             [ "2 dhollair agus 23 ceinteanna"+             , "dhá dhollair 23 ceinteanna"+             , "2 dhollair 23"+             , "dhá dhollair agus 23"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29.99"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rúpaí"+             , "20Rs"+             , "Rs20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupees 43"+             , "fiche rúpaí 43"+             ]+  , examples (AmountOfMoneyValue INR 33)+             [ "INR33"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "naoi bpunt"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3.01"+             , "GBP 3.01"+             ]+  ]
+ Duckling/AmountOfMoney/GA/Rules.hs view
@@ -0,0 +1,159 @@+-- 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 #-}++module Duckling.AmountOfMoney.GA.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "n?dh?oll?ai?rs?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cents?|g?ch?eint(eanna)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleThartArAmountofmoney :: Rule+ruleThartArAmountofmoney = Rule+  { name = "thart ar <amount-of-money>"+  , pattern =+    [ regex "thart( ar)?|beagnach|breis (is|agus)"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "pounds?|b?ph?unt"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "agus|is"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleInr :: Rule+ruleInr = Rule+  { name = "INR"+  , pattern =+    [ regex "r(\x00fa|u)pa(\x00ed|i)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly INR+  }++ruleIntersectAgusNumeral :: Rule+ruleIntersectAgusNumeral = Rule+  { name = "intersect (agus number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "agus|is"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleAmountofmoneyGlan :: Rule+ruleAmountofmoneyGlan = Rule+  { name = "<amount-of-money> glan"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "glan|baileach|(go )?d(\x00ed|i)reach"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAmountofmoneyGlan+  , ruleCent+  , ruleDollar+  , ruleInr+  , ruleIntersect+  , ruleIntersectAgusNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , rulePounds+  , ruleThartArAmountofmoney+  ]
+ Duckling/AmountOfMoney/HR/Corpus.hs view
@@ -0,0 +1,96 @@+-- 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.AmountOfMoney.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.AmountOfMoney.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "deset dolara"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "deset centa"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue Dollar 2.23)+             [ "2 dolara i 23 centa"+             , "dva dolara 23 centa"+             , "2 dolara 23"+             , "dva dolara i 23"+             ]+  , examples (AmountOfMoneyValue HRK 2.23)+             [ "2 kune i 23 lipe"+             , "dvije kune 23 lipe"+             , "2 kune 23"+             , "dvije kune i 23"+             ]+  , examples (AmountOfMoneyValue HRK 100)+             [ "100 kuna"+             , "sto kuna"+             ]+  , examples (AmountOfMoneyValue HRK 200)+             [ "200 kuna"+             , "dvije stotine kuna"+             , "dvjesto kuna"+             , "dvjesta kuna"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rupija"+             , "20Rs"+             , "Rs20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupija 43"+             , "dvadeset rupija 43"+             ]+  , examples (AmountOfMoneyValue INR 33)+             [ "INR33"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "devet funti"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  ]
+ Duckling/AmountOfMoney/HR/Rules.hs view
@@ -0,0 +1,200 @@+-- 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 #-}++module Duckling.AmountOfMoney.HR.Rules+  ( rules ) where++import Data.Maybe+import Data.String+import Data.Text (Text)+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.Types (NumeralData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import qualified Duckling.Numeral.Types as TNumeral++ruleIntersectAndNumber :: Rule+ruleIntersectAndNumber = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "i"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleSar :: Rule+ruleSar = Rule+  { name = "SAR"+  , pattern =+    [ regex "saudijskirijal|saudi rijal?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly SAR+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "dolar(a|i|e)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cent(i|a)?|penij(i|a)?|c|\x00a2|lp|lip(a|e)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleIntersectIXLipa :: Rule+ruleIntersectIXLipa = Rule+  { name = "intersect (i X lipa)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "i"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePound :: Rule+rulePound = Rule+  { name = "£"+  , pattern =+    [ regex "funt(a|e|i)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleHrk :: Rule+ruleHrk = Rule+  { name = "HRK"+  , pattern =+    [ regex "kn|(hrvatsk(a|ih|e) )?kun(a|e)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly HRK+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleOtherPounds :: Rule+ruleOtherPounds = Rule+  { name = "other pounds"+  , pattern =+    [ regex "(egipatska|libanonska) ?funta"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "egipatska"  -> Just . Token AmountOfMoney $ currencyOnly EGP+        "libanonska" -> Just . Token AmountOfMoney $ currencyOnly LBP+        _            -> Nothing+      _ -> Nothing+  }++ruleInr :: Rule+ruleInr = Rule+  { name = "INR"+  , pattern =+    [ regex "rupija?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly INR+  }++ruleKwd :: Rule+ruleKwd = Rule+  { name = "KWD"+  , pattern =+    [ regex "kuvajtski ?dinar"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly KWD+  }++ruleQar :: Rule+ruleQar = Rule+  { name = "QAR"+  , pattern =+    [ regex "katarski(i| )rijal"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly QAR+  }++ruleAed :: Rule+ruleAed = Rule+  { name = "AED"+  , pattern =+    [ regex "drahma?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleDollar+  , rulePound+  , ruleOtherPounds+  , ruleAed+  , ruleCent+  , ruleHrk+  , ruleInr+  , ruleIntersect+  , ruleIntersectAndNumber+  , ruleIntersectIXLipa+  , ruleIntersectXCents+  , ruleKwd+  , ruleQar+  , ruleSar+  ]
+ Duckling/AmountOfMoney/Helpers.hs view
@@ -0,0 +1,48 @@+-- 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 #-}++module Duckling.AmountOfMoney.Helpers+  ( currencyOnly+  , financeWith+  , withCents+  , withValue+  )+  where++import Prelude++import Duckling.Dimensions.Types+import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import Duckling.Types hiding (Entity(..))++-- -----------------------------------------------------------------+-- Patterns++financeWith :: (AmountOfMoneyData -> t) -> (t -> Bool) -> PatternItem+financeWith f pred = Predicate $ \x ->+  case x of+    (Token AmountOfMoney x) -> pred (f x)+    _ -> False++-- -----------------------------------------------------------------+-- Production++currencyOnly :: Currency -> AmountOfMoneyData+currencyOnly c = AmountOfMoneyData {currency = c, value = Nothing}++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}
+ Duckling/AmountOfMoney/ID/Corpus.hs view
@@ -0,0 +1,82 @@+-- 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.AmountOfMoney.ID.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ID}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "sepuluh dolar"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue Dollar 2)+             [ "2 dola"+             , "dua dolar"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             , "dua puluh Euro"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue IDR 315)+             [ "Rp. 315,00"+             ]+  , examples (AmountOfMoneyValue IDR 20)+             [ "Rp 20"+             , "20 Rupiah"+             , "20Rp"+             , "Rp20"+             ]+  , examples (AmountOfMoneyValue IDR 33000)+             [ "IDR33000"+             , "IDR 33.000"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "sembilan pound"+             , "sembilan pound sterling"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  , examples (AmountOfMoneyValue JPY 10)+             [ "10 yen"+             , "10¥"+             , "10 ¥."+             ]+  ]
+ Duckling/AmountOfMoney/ID/Rules.hs view
@@ -0,0 +1,84 @@+-- 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 #-}++module Duckling.AmountOfMoney.ID.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "dolar?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleIdr :: Rule+ruleIdr = Rule+  { name = "IDR"+  , pattern =+    [ regex "rp\\.?|rupiah"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly IDR+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "pound( sterling)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleJpy :: Rule+ruleJpy = Rule+  { name = "JPY"+  , pattern =+    [ regex "\x00a5\\."+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly JPY+  }++rules :: [Rule]+rules =+  [ ruleDollar+  , ruleIdr+  , ruleIntersect+  , ruleJpy+  , rulePounds+  ]
+ Duckling/AmountOfMoney/KO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "십달러"+             , "십불"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "십센트"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "만달러"+             , "만불"+             ]+  , examples (AmountOfMoneyValue Dollar 1.23)+             [ "일점이삼달러"+             , "일쩜이삼달러"+             , "일점이삼불"+             , "일쩜이삼불"+             ]+  , examples (AmountOfMoneyValue Dollar 2.23)+             [ "이달러이십삼센트"+             , "이불이십삼센트"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "이십유로"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "이십구점구구유로"+             , "EUR29.99"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "구파운드"+             ]+  , examples (AmountOfMoneyValue KRW 27350000)+             [ "이천칠백삼십오만원"+             , "27,350,000원"+             , "27350000원"+             ]+  , examples (AmountOfMoneyValue KRW 27000)+             [ "이만칠천원"+             , "27,000원"+             , "27000원"+             ]+  , examples (AmountOfMoneyValue KRW 100)+             [ "백원"+             , "100원"+             ]+  , examples (AmountOfMoneyValue KRW 10)+             [ "십원"+             , "10원"+             , "10₩"+             ]+  ]
+ Duckling/AmountOfMoney/KO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.KO.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Types++ruleAmountofmoneyAbout :: Rule+ruleAmountofmoneyAbout = Rule+  { name = "<amount-of-money> about"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "\xc815\xb3c4|\xcbe4"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> Just token+      _ -> Nothing+  }++ruleAud :: Rule+ruleAud = Rule+  { name = "AUD"+  , pattern =+    [ regex "\xd638\xc8fc\xb2ec\xb7ec"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AUD+  }++ruleKrw :: Rule+ruleKrw = Rule+  { name = "₩"+  , pattern =+    [ regex "\x20a9|\xc6d0"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly KRW+  }++ruleAboutAmountofmoney :: Rule+ruleAboutAmountofmoney = Rule+  { name = "about <amount-of-money>"+  , pattern =+    [ regex "\xc57d|\xb300\xcda9|\xc5bc\xcd94"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cents?|\xc13c(\xd2b8|\xce20)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleExactlyAmountofmoney :: Rule+ruleExactlyAmountofmoney = Rule+  { name = "exactly <amount-of-money>"+  , pattern =+    [ regex "\xb531|\xc815\xd655\xd788"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleEuro :: Rule+ruleEuro = Rule+  { name = "€"+  , pattern =+    [ regex "\x20ac|\xc720\xb85c"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly EUR+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "\xb2ec\xb7ec|\xbd88"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleInr :: Rule+ruleInr = Rule+  { name = "INR"+  , pattern =+    [ regex "\xb8e8\xd53c|\xc778\xb3c4\xb8e8\xd53c"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly INR+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "\xd30c\xc6b4\xb4dc|\xc601\xad6d\xd30c\xc6b4\xb4dc"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "dirham"+  , pattern =+    [ regex "dirhams?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleAboutAmountofmoney+  , ruleAmountofmoneyAbout+  , ruleAud+  , ruleCent+  , ruleDirham+  , ruleDollar+  , ruleEuro+  , ruleExactlyAmountofmoney+  , ruleInr+  , ruleIntersectXCents+  , ruleKrw+  , rulePounds+  ]
+ Duckling/AmountOfMoney/NB/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.NB.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NB}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "ti dollar"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "ti øre"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue NOK 10)+             [ "10kroner"+             , "10kr"+             , "ti kroner"+             , "10 NOK"+             ]+  , examples (AmountOfMoneyValue NOK 2.23)+             [ "2 kroner og 23 øre"+             , "to kroner 23 øre"+             , "to kroner og 23 øre"+             , "to kr 23"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euro"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rupees"+             , "20Rs"+             , "Rs20"+             , "INR20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupees 43"+             , "tjue rupees 43"+             , "tjue rupees 43¢"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "ni pund"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  ]
+ Duckling/AmountOfMoney/NB/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.NB.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency (..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "og"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleAboutAmountofmoney :: Rule+ruleAboutAmountofmoney = Rule+  { name = "about <amount-of-money>"+  , pattern =+    [ regex "omtrent|cirka|rundt|ca"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cents?|penn(y|ies)|(\x00f8)re"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (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 =+    [ financeWith TAmountOfMoney.value isJust+    , regex "og"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleNok :: Rule+ruleNok = Rule+  { name = "NOK"+  , pattern =+    [ regex "kr(oner)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly NOK+  }++rulePound :: Rule+rulePound = Rule+  { name = "£"+  , pattern =+    [ regex "pund?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "og"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "AED"+  , pattern =+    [ regex "dirhams?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleAboutAmountofmoney+  , ruleCent+  , ruleDirham+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleIntersectXCentsWithAnd+  , ruleNok+  , rulePound+  ]
+ Duckling/AmountOfMoney/PT/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.PT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "dez dolares"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "nove libras"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  , examples (AmountOfMoneyValue PTS 15)+             [ "15 Pt"+             , "15pta"+             , "15Ptas"+             ]+  , examples (AmountOfMoneyValue BRL 15)+             [ "15 reais"+             , "15reais"+             , "15 Reais"+             , "BRL 15"+             ]+  , examples (AmountOfMoneyValue BRL 2.0)+             [ "R$2,00"+             , "R$ 2,00"+             , "2,00 reais"+             ]+  ]
+ Duckling/AmountOfMoney/PT/Rules.hs view
@@ -0,0 +1,133 @@+-- 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 #-}++module Duckling.AmountOfMoney.PT.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "e"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "dolares?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "centavos?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "libras?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "e"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleBrl :: Rule+ruleBrl = Rule+  { name = "BRL"+  , pattern =+    [ regex "reais|r\\$"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly BRL+  }++rules :: [Rule]+rules =+  [ ruleBrl+  , ruleCent+  , ruleDollar+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , rulePounds+  ]
+ Duckling/AmountOfMoney/RO/Corpus.hs view
@@ -0,0 +1,120 @@+-- 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.AmountOfMoney.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue RON 10)+             [ "10 lei"+             , "10 roni"+             , "10 RON"+             ]+  , examples (AmountOfMoneyValue Cent 50)+             [ "50 bani"+             , "50 BANI"+             ]+  , examples (AmountOfMoneyValue RON 10.5)+             [ "10,5 lei"+             , "10,5 ron"+             , "10 lei si 50 bani"+             ]+  , examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "zece dolari"+             , "10 dolari"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "zece centi"+             , "zece cenți"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "$10000"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue Dollar 1)+             [ "1 dolar"+             , "un dolar"+             , "$1"+             ]+  , examples (AmountOfMoneyValue Cent 2)+             [ "2 centi"+             ]+  , examples (AmountOfMoneyValue Cent 23)+             [ "23 centi"+             ]+  , examples (AmountOfMoneyValue Dollar 2.23)+             [ "2 dolari si 23 centi"+             , "2 dolari și 23 cenți"+             , "doi dolari si douăzeci si trei centi"+             , "doi dolari și douăzeci și trei cenți"+             , "2 dolari 23 centi"+             , "doi dolari si 23"+             , "doi dolari și 23"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euro"+             , "20 Euro"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "noua lir"+             , "nouă lire"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  , examples (AmountOfMoneyValue QAR 1)+             [ "un rial qatarian"+             , "1 rial qataria"+             ]+  , examples (AmountOfMoneyValue EGP 10)+             [ "zece lira egiptiana"+             ]+  , examples (AmountOfMoneyValue LBP 1)+             [ "una liră libaneză"+             ]+  , examples (AmountOfMoneyValue INR 42)+             [ "42 rupii"+             , "Rs. 42"+             ]+  , examples (AmountOfMoneyValue KWD 1)+             [ "un dinar kuweitian"+             ]+  , examples (AmountOfMoneyValue AED 2)+             [ "2 dirhami"+             ]+  , examples (AmountOfMoneyValue SAR 1)+             [ "1 rial saudit"+             , "un rial saudi"+             ]+  ]
+ Duckling/AmountOfMoney/RO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.RO.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import Duckling.Types++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "(s|\x0219)i"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleRiyals :: Rule+ruleRiyals = Rule+  { name = "riyals"+  , pattern =+    [ regex "rial (saudit?|qatarian?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "saudi"     -> Just . Token AmountOfMoney $ currencyOnly SAR+        "saudit"    -> Just . Token AmountOfMoney $ currencyOnly SAR+        "qataria"   -> Just . Token AmountOfMoney $ currencyOnly QAR+        "qatarian"  -> Just . Token AmountOfMoney $ currencyOnly QAR+        _           -> Nothing+      _ -> Nothing+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "dolari?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++rulePrecisionAmountofmoney :: Rule+rulePrecisionAmountofmoney = Rule+  { name = "about/exactly <amount-of-money>"+  , pattern =+    [ regex "exact|cam|aprox(\\.|imativ)?|aproape|(i|\x00ee)n jur (de)?"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent|bani"+  , pattern =+    [ regex "bani?|cen(t|\x021b)i?|c|\x00a2"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleRon :: Rule+ruleRon = Rule+  { name = "RON"+  , pattern =+    [ regex "roni|lei"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly RON+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "(s|\x0219)i"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "lire?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleOtherPounds :: Rule+ruleOtherPounds = Rule+  { name = "other pounds"+  , pattern =+    [ regex "lir(a|\x0103) (egiptian|libanez)(a|\x0103)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (_:match:_)):_) -> case Text.toLower match of+        "egiptian" -> Just . Token AmountOfMoney $ currencyOnly EGP+        "libanez"  -> Just . Token AmountOfMoney $ currencyOnly LBP+        _          -> Nothing+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleInr :: Rule+ruleInr = Rule+  { name = "INR"+  , pattern =+    [ regex "rupii?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly INR+  }++ruleKwd :: Rule+ruleKwd = Rule+  { name = "KWD"+  , pattern =+    [ regex "dinar kuweitian"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly KWD+  }++ruleAed :: Rule+ruleAed = Rule+  { name = "AED"+  , pattern =+    [ regex "dirhami?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleAed+  , ruleCent+  , ruleDollar+  , ruleInr+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleKwd+  , ruleOtherPounds+  , rulePounds+  , rulePrecisionAmountofmoney+  , ruleRiyals+  , ruleRon+  ]
+ Duckling/AmountOfMoney/Rules.hs view
@@ -0,0 +1,129 @@+-- 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 #-}++module Duckling.AmountOfMoney.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.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types     as TNumeral+import Duckling.Regex.Types+import Duckling.Types++currencies :: HashMap Text Currency+currencies = HashMap.fromList+  [ ("aed", AED)+  , ("aud", AUD)+  , ("brl", BRL)+  , ("\x00a2", Cent)+  , ("c", Cent)+  , ("$", Dollar)+  , ("dollar", Dollar)+  , ("dollars", Dollar)+  , ("egp", EGP)+  , ("\x20ac", EUR)+  , ("eur", EUR)+  , ("euro", EUR)+  , ("euros", EUR)+  , ("eurs", EUR)+  , ("\x20acur", EUR)+  , ("\x20acuro", EUR)+  , ("\x20acuros", EUR)+  , ("\x20acurs", EUR)+  , ("gbp", GBP)+  , ("hrk", HRK)+  , ("idr", IDR)+  , ("inr", INR)+  , ("rs", INR)+  , ("rs.", INR)+  , ("rupee", INR)+  , ("rupees", INR)+  , ("\x00a5", JPY)+  , ("jpy", JPY)+  , ("yen", JPY)+  , ("krw", KRW)+  , ("kwd", KWD)+  , ("lbp", LBP)+  , ("nok", NOK)+  , ("\x00a3", Pound)+  , ("pt", PTS)+  , ("pta", PTS)+  , ("ptas", PTS)+  , ("pts", PTS)+  , ("qar", QAR)+  , ("ron", RON)+  , ("sar", SAR)+  , ("sek", SEK)+  , ("sgd", SGD)+  , ("usd", USD)+  , ("us$", USD)+  , ("vnd", VND)+  ]++ruleCurrencies :: Rule+ruleCurrencies = Rule+  { name = "currencies"+  , pattern =+    [ regex "(aed|aud|brl|\x00a2|c|\\$|dollars?|egp|(e|\x20ac)uro?s?|\x20ac|gbp|hrk|idr|inr|\x00a5|jpy|krw|kwd|lbp|nok|\x00a3|pta?s?|qar|rs\\.?|ron|rupees?|sar|sek|sgb|us(d|\\$)|vnd|yen)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        c <- HashMap.lookup (Text.toLower match) currencies+        Just . Token AmountOfMoney $ currencyOnly c+      _ -> Nothing+  }++ruleAmountUnit :: Rule+ruleAmountUnit = Rule+  { name = "<amount> <unit>"+  , pattern =+    [ dimension Numeral+    , financeWith TAmountOfMoney.value isNothing+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.currency = c}):+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++ruleUnitAmount :: Rule+ruleUnitAmount = Rule+  { name = "<unit> <amount>"+  , pattern =+    [ financeWith TAmountOfMoney.value isNothing+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.currency = c}):+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> Just . Token AmountOfMoney . withValue v $ currencyOnly c+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAmountUnit+  , ruleCurrencies+  , ruleUnitAmount+  ]
+ Duckling/AmountOfMoney/SV/Corpus.hs view
@@ -0,0 +1,91 @@+-- 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.AmountOfMoney.SV.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = SV}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "tio dollar"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "tio öre"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10.000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1,23"+             ]+  , examples (AmountOfMoneyValue SEK 10)+             [ "10kronor"+             , "10kr"+             , "10 kr"+             , "tio kronor"+             , "10 SEK"+             ]+  , examples (AmountOfMoneyValue SEK 2.23)+             [ "2 kronor och 23 öre"+             , "två kronor 23 öre"+             , "två kronor och 23 öre"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euro"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29,99"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rupees"+             , "20Rs"+             , "Rs20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupees 43"+             , "tjugo rupees 43"+             ]+  , examples (AmountOfMoneyValue INR 33)+             [ "INR33"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "nio pund"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3,01"+             , "GBP 3,01"+             ]+  , examples (AmountOfMoneyValue NOK 10)+             [ "10 norska kronor"+             , "10 nkr"+             ]+  ]
+ Duckling/AmountOfMoney/SV/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.SV.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleIntersectAndNumeral :: Rule+ruleIntersectAndNumeral = Rule+  { name = "intersect (and number)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "och"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleAboutAmountofmoney :: Rule+ruleAboutAmountofmoney = Rule+  { name = "about <amount-of-money>"+  , pattern =+    [ regex "omkring|cirka|runt|ca"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "cents?|penn(y|ies)|\x00f6re"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++ruleExactlyAmountofmoney :: Rule+ruleExactlyAmountofmoney = Rule+  { name = "exactly <amount-of-money>"+  , pattern =+    [ regex "exakt|precis"+    , financeWith TAmountOfMoney.value isJust+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntersectXCents :: Rule+ruleIntersectXCents = Rule+  { name = "intersect (X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleNok :: Rule+ruleNok = Rule+  { name = "NOK"+  , pattern =+    [ regex "norska kronor|nkr"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly NOK+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "pund?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersectAndXCents :: Rule+ruleIntersectAndXCents = Rule+  { name = "intersect (and X cents)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "och"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleSek :: Rule+ruleSek = Rule+  { name = "SEK"+  , pattern =+    [ regex "kr(onor)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly SEK+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "AED"+  , pattern =+    [ regex "dirhams?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleAboutAmountofmoney+  , ruleCent+  , ruleDirham+  , ruleExactlyAmountofmoney+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectAndXCents+  , ruleIntersectXCents+  , ruleNok+  , rulePounds+  , ruleSek+  ]
+ Duckling/AmountOfMoney/Types.hs view
@@ -0,0 +1,109 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.AmountOfMoney.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Text (Text)+import GHC.Generics+import Prelude++import Duckling.Resolve (Resolve(..))++data Currency+  -- ambiguous+  = Cent+  | Dollar+  | Pound+  | Unnamed -- e.g. bucks+  -- unambiguous+  | AED+  | AUD+  | BRL+  | EGP+  | EUR+  | GBP+  | HRK+  | IDR+  | INR+  | JPY+  | KRW+  | KWD+  | LBP+  | NOK+  | PTS+  | QAR+  | RON+  | SAR+  | SEK+  | SGD+  | USD+  | VND+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++instance ToJSON Currency where+  toJSON Cent    = "cent"+  toJSON Dollar  = "$"+  toJSON Pound   = "\x00a3"+  toJSON Unnamed = "unknown"+  toJSON AED     = "AED"+  toJSON AUD     = "AUD"+  toJSON BRL     = "BRL"+  toJSON EGP     = "EGP"+  toJSON EUR     = "EUR"+  toJSON GBP     = "GBP"+  toJSON HRK     = "HRK"+  toJSON IDR     = "IDR"+  toJSON INR     = "INR"+  toJSON JPY     = "JPY"+  toJSON KRW     = "KRW"+  toJSON KWD     = "KWD"+  toJSON LBP     = "LBP"+  toJSON NOK     = "NOK"+  toJSON PTS     = "PTS"+  toJSON QAR     = "QAR"+  toJSON RON     = "RON"+  toJSON SAR     = "SAR"+  toJSON SEK     = "SEK"+  toJSON SGD     = "SGD"+  toJSON USD     = "USD"+  toJSON VND     = "VND"++data AmountOfMoneyData = AmountOfMoneyData+  { value    :: Maybe Double+  , currency :: Currency+  }+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++data AmountOfMoneyValue = AmountOfMoneyValue+  { vCurrency :: Currency+  , vValue    :: Double+  }+  deriving (Eq, Show)++instance Resolve AmountOfMoneyData where+  type ResolvedValue AmountOfMoneyData = AmountOfMoneyValue+  resolve _ AmountOfMoneyData {value = Nothing} = Nothing+  resolve _ AmountOfMoneyData {value = Just value, currency} =+    Just AmountOfMoneyValue {vValue = value, vCurrency = currency}++instance ToJSON AmountOfMoneyValue where+  toJSON AmountOfMoneyValue {vCurrency, vValue} = object+    [ "type"  .= ("value" :: Text)+    , "value" .= vValue+    , "unit"  .= vCurrency+    ]
+ Duckling/AmountOfMoney/VI/Corpus.hs view
@@ -0,0 +1,103 @@+-- 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.AmountOfMoney.VI.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.AmountOfMoney.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = VI}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (AmountOfMoneyValue Dollar 10)+             [ "$10"+             , "10$"+             , "mười đô"+             , "mười đô la"+             , "mười đô mỹ"+             ]+  , examples (AmountOfMoneyValue Cent 10)+             [ "mười xen"+             , "mười xu"+             ]+  , examples (AmountOfMoneyValue Dollar 10000)+             [ "$10,000"+             , "10K$"+             , "$10k"+             ]+  , examples (AmountOfMoneyValue USD 1.23)+             [ "USD1.23"+             ]+  , examples (AmountOfMoneyValue Dollar 2.23)+             [ "2 đô la và 23 xen"+             , "hai đô la và 23 xen"+             , "2 đô 23 xu"+             , "hai đô 23"+             , "2 chấm 23 đô la"+             , "hai phẩy 23 đô"+             ]+  , examples (AmountOfMoneyValue VND 10)+             [ "mười đồng"+             ]+  , examples (AmountOfMoneyValue VND 10000)+             [ "10,000 đồng"+             , "10K đồng"+             , "10k đồng"+             ]+  , examples (AmountOfMoneyValue VND 1000)+             [ "1000 VNĐ"+             , "VN$1000"+             ]+  , examples (AmountOfMoneyValue EUR 20)+             [ "20€"+             , "20 euros"+             , "20 Euro"+             , "20 Euros"+             , "EUR 20"+             ]+  , examples (AmountOfMoneyValue EUR 29.99)+             [ "EUR29.99"+             ]+  , examples (AmountOfMoneyValue INR 20)+             [ "Rs. 20"+             , "Rs 20"+             , "20 Rupees"+             , "20Rs"+             , "Rs20"+             ]+  , examples (AmountOfMoneyValue INR 20.43)+             [ "20 Rupees 43"+             , "hai mươi rupees 43"+             , "hai mươi rupees 43 xen"+             ]+  , examples (AmountOfMoneyValue INR 33)+             [ "INR33"+             ]+  , examples (AmountOfMoneyValue Pound 9)+             [ "£9"+             , "chín pounds"+             ]+  , examples (AmountOfMoneyValue GBP 3.01)+             [ "GBP3.01"+             , "GBP 3.01"+             ]+  , examples (AmountOfMoneyValue AED 1)+             [ "1 AED."+             , "1 dirham"+             ]+  ]
+ Duckling/AmountOfMoney/VI/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.AmountOfMoney.VI.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.AmountOfMoney.Helpers+import Duckling.AmountOfMoney.Types (Currency(..), AmountOfMoneyData (..))+import qualified Duckling.AmountOfMoney.Types as TAmountOfMoney+import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleNg :: Rule+ruleNg = Rule+  { name = "đồng"+  , pattern =+    [ regex "\x0111\x1ed3ng?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly VND+  }++ruleDollar :: Rule+ruleDollar = Rule+  { name = "$"+  , pattern =+    [ regex "\x0111\x00f4 la|\x0111\x00f4 m\x1ef9|\x0111(\x00f4)?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Dollar+  }++ruleVnd :: Rule+ruleVnd = Rule+  { name = "VNĐ"+  , pattern =+    [ regex "vn(\x0110|\\$)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly VND+  }++ruleCent :: Rule+ruleCent = Rule+  { name = "cent"+  , pattern =+    [ regex "xen|xu?|penn(y|ies)"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Cent+  }++rulePounds :: Rule+rulePounds = Rule+  { name = "£"+  , pattern =+    [ regex "pounds?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly Pound+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , dimension Numeral+    ]+  , 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 =+    [ financeWith TAmountOfMoney.value isJust+    , regex "v\x00e0"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token Numeral (NumeralData {TNumeral.value = c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectXXuxen :: Rule+ruleIntersectXXuxen = Rule+  { name = "intersect (X xu|xen)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleIntersectVXXuxen :: Rule+ruleIntersectVXXuxen = Rule+  { name = "intersect (và X xu|xen)"+  , pattern =+    [ financeWith TAmountOfMoney.value isJust+    , regex "v\x00e0"+    , financeWith TAmountOfMoney.currency (== Cent)+    ]+  , prod = \tokens -> case tokens of+      (Token AmountOfMoney fd:+       _:+       Token AmountOfMoney (AmountOfMoneyData {TAmountOfMoney.value = Just c}):+       _) -> Just . Token AmountOfMoney $ withCents c fd+      _ -> Nothing+  }++ruleDirham :: Rule+ruleDirham = Rule+  { name = "AED"+  , pattern =+    [ regex "AED\\.|dirhams?"+    ]+  , prod = \_ -> Just . Token AmountOfMoney $ currencyOnly AED+  }++rules :: [Rule]+rules =+  [ ruleCent+  , ruleDirham+  , ruleDollar+  , ruleIntersect+  , ruleIntersectAndNumeral+  , ruleIntersectVXXuxen+  , ruleIntersectXXuxen+  , ruleNg+  , rulePounds+  , ruleVnd+  ]
+ Duckling/Api.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Api+  ( analyze+  , formatToken+  , parse+  , supportedDimensions+  ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.HashSet (HashSet)+import qualified Data.HashSet as HashSet+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import TextShow++import Duckling.Dimensions.Types+import Duckling.Dimensions+import Duckling.Engine+import Duckling.Lang+import Duckling.Ranking.Classifiers+import Duckling.Ranking.Rank+import Duckling.Resolve+import Duckling.Rules+import Duckling.Types++-- | Parses `input` and returns a curated list of entities found.+parse :: Text -> Context -> [Some Dimension] -> [Entity]+parse input ctx = map (formatToken input) . analyze input ctx . HashSet.fromList++supportedDimensions :: HashMap Lang [Some 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 -> HashSet (Some Dimension) -> [ResolvedToken]+analyze input context@Context{..} targets =+  rank (classifiers lang) targets+  . filter (\(Resolved{node = Node{token = (Token d _)}}) ->+      HashSet.null targets || HashSet.member (This d) targets+    )+  $ parseAndResolve (rulesFor lang targets) input context++-- | Converts the resolved token to the API format+formatToken :: Text -> ResolvedToken -> Entity+formatToken sentence (Resolved (Range start end) (Node{token=Token dimension _}) jsonValue) =+  Entity (toName dimension) body val start end+  where+    body = Text.drop start $ Text.take end sentence+    val = toJText jsonValue
+ Duckling/Core.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE NoRebindableSyntax #-}++-- | Everything needed to run Duckling.++module Duckling.Core+  ( Context(..)+  , Dimension(..)+  , fromName+  , Entity(..)+  , Lang(..)+  , Some(..)+  , toName++  -- Duckling API+  , parse+  , supportedDimensions++  -- Reference time builders+  , currentReftime+  , makeReftime+  ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import Data.Time+import Data.Time.LocalTime.TimeZone.Series+import Prelude++import Duckling.Api+import Duckling.Dimensions.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Types++-- | Builds a `DucklingTime` for timezone `tz` at `utcTime`.+-- If no `series` found for `tz`, uses UTC.+makeReftime :: HashMap Text TimeZoneSeries -> Text -> UTCTime -> DucklingTime+makeReftime series tz utcTime = DucklingTime $ ZoneSeriesTime ducklingTime tzs+  where+    tzs = HashMap.lookupDefault (TimeZoneSeries utc []) tz series+    ducklingTime = toUTC $ utcToLocalTime' tzs utcTime++-- | Builds a `DucklingTime` for timezone `tz` at current time.+-- If no `series` found for `tz`, uses UTC.+currentReftime :: HashMap Text TimeZoneSeries -> Text -> IO DucklingTime+currentReftime series tz = do+  utcNow <- getCurrentTime+  return $ makeReftime series tz utcNow
+ Duckling/Debug.hs view
@@ -0,0 +1,85 @@+-- 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 NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Debug+  ( allParses+  , debug+  , debugContext+  , fullParses+  , ptree+  ) where++import qualified Data.HashSet as HashSet+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.IO as Text+import Prelude++import Duckling.Api+import Duckling.Dimensions.Types+import Duckling.Engine+import Duckling.Lang+import Duckling.Resolve+import Duckling.Rules+import Duckling.Testing.Types+import Duckling.Types++-- -----------------------------------------------------------------+-- API++debug :: Lang -> Text -> [Some Dimension] -> IO [Entity]+debug l = debugContext testContext {lang = l}++allParses :: Lang -> Text -> [Some Dimension] -> IO [Entity]+allParses l sentence targets = debugTokens sentence $ parses l sentence targets++fullParses :: Lang -> Text -> [Some 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++ptree :: Text -> ResolvedToken -> IO ()+ptree sentence Resolved {node} = pnode sentence 0 node++-- -----------------------------------------------------------------+-- Internals++parses :: Lang -> Text -> [Some Dimension] -> [ResolvedToken]+parses l sentence targets = flip filter tokens $+  \(Resolved {node = Node{token = (Token d _)}}) ->+    case targets of+      [] -> True+      _ -> elem (This d) targets+  where+    tokens = parseAndResolve rules sentence testContext {lang = l}+    rules = rulesFor l $ HashSet.fromList targets++debugContext :: Context -> Text -> [Some Dimension] -> IO [Entity]+debugContext context sentence targets =+  debugTokens sentence . analyze sentence context $ HashSet.fromList targets++debugTokens :: Text -> [ResolvedToken] -> IO [Entity]+debugTokens sentence tokens = do+  mapM_ (ptree sentence) tokens+  return $ map (formatToken sentence) tokens++pnode :: Text -> Int -> Node -> IO ()+pnode sentence depth Node {children, rule, nodeRange = Range start end} = do+  Text.putStrLn out+  mapM_ (pnode sentence (depth + 1)) children+  where+    out = Text.concat [ Text.replicate depth "-- ", name, " (", body, ")" ]+    name = fromMaybe "regex" rule+    body = Text.drop start $ Text.take end sentence
+ Duckling/Dimensions.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Dimensions+  ( allDimensions+  , explicitDimensions+  ) where++import Data.HashSet (HashSet)+import Prelude+import qualified Data.HashSet as HashSet++import Duckling.Dimensions.Types+import qualified Duckling.Dimensions.Common as CommonDimensions+import qualified Duckling.Dimensions.AR as ARDimensions+import qualified Duckling.Dimensions.DA as DADimensions+import qualified Duckling.Dimensions.DE as DEDimensions+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.FR as FRDimensions+import qualified Duckling.Dimensions.GA as GADimensions+import qualified Duckling.Dimensions.HE as HEDimensions+import qualified Duckling.Dimensions.HR as HRDimensions+import qualified Duckling.Dimensions.ID as IDDimensions+import qualified Duckling.Dimensions.IT as ITDimensions+import qualified Duckling.Dimensions.JA as JADimensions+import qualified Duckling.Dimensions.KO as KODimensions+import qualified Duckling.Dimensions.MY as MYDimensions+import qualified Duckling.Dimensions.NB as NBDimensions+import qualified Duckling.Dimensions.NL as NLDimensions+import qualified Duckling.Dimensions.PL as PLDimensions+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.SV as SVDimensions+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+import Duckling.Lang++allDimensions :: Lang -> [Some Dimension]+allDimensions lang = CommonDimensions.allDimensions ++ langDimensions lang++-- | Augments `targets` with all dependent dimensions.+explicitDimensions :: HashSet (Some Dimension) -> HashSet (Some 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)++langDimensions :: Lang -> [Some Dimension]+langDimensions AR = ARDimensions.allDimensions+langDimensions DA = DADimensions.allDimensions+langDimensions DE = DEDimensions.allDimensions+langDimensions EN = ENDimensions.allDimensions+langDimensions ES = ESDimensions.allDimensions+langDimensions ET = ETDimensions.allDimensions+langDimensions FR = FRDimensions.allDimensions+langDimensions GA = GADimensions.allDimensions+langDimensions HE = HEDimensions.allDimensions+langDimensions HR = HRDimensions.allDimensions+langDimensions ID = IDDimensions.allDimensions+langDimensions IT = ITDimensions.allDimensions+langDimensions JA = JADimensions.allDimensions+langDimensions KO = KODimensions.allDimensions+langDimensions MY = MYDimensions.allDimensions+langDimensions NB = NBDimensions.allDimensions+langDimensions NL = NLDimensions.allDimensions+langDimensions PL = PLDimensions.allDimensions+langDimensions PT = PTDimensions.allDimensions+langDimensions RO = RODimensions.allDimensions+langDimensions RU = RUDimensions.allDimensions+langDimensions SV = SVDimensions.allDimensions+langDimensions TR = TRDimensions.allDimensions+langDimensions UK = UKDimensions.allDimensions+langDimensions VI = VIDimensions.allDimensions+langDimensions ZH = ZHDimensions.allDimensions
+ Duckling/Dimensions/AR.hs view
@@ -0,0 +1,19 @@+-- 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.AR+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/Common.hs view
@@ -0,0 +1,21 @@+-- 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.Common+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Email+  , This AmountOfMoney+  , This PhoneNumber+  , This Url+  ]
+ Duckling/Dimensions/DA.hs view
@@ -0,0 +1,21 @@+-- 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.DA+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/DE.hs view
@@ -0,0 +1,21 @@+-- 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.DE+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/EN.hs view
@@ -0,0 +1,25 @@+-- 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.EN+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/ES.hs view
@@ -0,0 +1,24 @@+-- 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.ES+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/ET.hs view
@@ -0,0 +1,19 @@+-- 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.ET+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/FR.hs view
@@ -0,0 +1,25 @@+-- 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.FR+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/GA.hs view
@@ -0,0 +1,24 @@+-- 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.GA+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/HE.hs view
@@ -0,0 +1,21 @@+-- 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.HE+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/HR.hs view
@@ -0,0 +1,25 @@+-- 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.HR+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/ID.hs view
@@ -0,0 +1,19 @@+-- 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.ID+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/IT.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++module Duckling.Dimensions.IT+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/JA.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++module Duckling.Dimensions.JA+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Temperature+  , This Time+  ]
+ Duckling/Dimensions/KO.hs view
@@ -0,0 +1,25 @@+-- 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.KO+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/MY.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.MY+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  ]
+ Duckling/Dimensions/NB.hs view
@@ -0,0 +1,21 @@+-- 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.NB+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/NL.hs view
@@ -0,0 +1,21 @@+-- 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.NL+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Numeral+  , This Ordinal+  , This Volume+  ]
+ Duckling/Dimensions/PL.hs view
@@ -0,0 +1,21 @@+-- 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.PL+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/PT.hs view
@@ -0,0 +1,25 @@+-- 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.PT+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/RO.hs view
@@ -0,0 +1,25 @@+-- 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.RO+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Distance+  , This Duration+  , This Numeral+  , This Ordinal+  , This Quantity+  , This Temperature+  , This Time+  , This Volume+  ]
+ Duckling/Dimensions/RU.hs view
@@ -0,0 +1,19 @@+-- 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.RU+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/SV.hs view
@@ -0,0 +1,21 @@+-- 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.SV+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/TR.hs view
@@ -0,0 +1,19 @@+-- 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.TR+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/Types.hs view
@@ -0,0 +1,181 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE TypeOperators #-}+++module Duckling.Dimensions.Types+  ( Some(..)+  , Dimension(..)++  , fromName+  , toName+  ) where++import Data.GADT.Compare+import Data.GADT.Show+import Data.Hashable+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Some+import Data.Text (Text)+-- Intentionally limit use of Typeable to avoid casting or typeOf usage+import Data.Typeable ((:~:)(..))+import TextShow (TextShow(..))+import qualified TextShow as TS+import Prelude++import Duckling.AmountOfMoney.Types (AmountOfMoneyData)+import Duckling.Distance.Types (DistanceData)+import Duckling.Duration.Types (DurationData)+import Duckling.Email.Types (EmailData)+import Duckling.Numeral.Types (NumeralData)+import Duckling.Ordinal.Types (OrdinalData)+import Duckling.PhoneNumber.Types (PhoneNumberData)+import Duckling.Quantity.Types (QuantityData)+import Duckling.Regex.Types (GroupMatch)+import Duckling.Temperature.Types (TemperatureData)+import Duckling.Time.Types (TimeData)+import Duckling.TimeGrain.Types (Grain)+import Duckling.Url.Types (UrlData)+import Duckling.Volume.Types (VolumeData)++-- -----------------------------------------------------------------+-- Dimension++-- | GADT for differentiating between dimensions+-- Each dimension should have its own constructor and provide the data structure+-- for its parsed data+data Dimension a where+  RegexMatch :: Dimension GroupMatch+  AmountOfMoney :: Dimension AmountOfMoneyData+  Distance :: Dimension DistanceData+  Duration :: Dimension DurationData+  Email :: Dimension EmailData+  Numeral :: Dimension NumeralData+  Ordinal :: Dimension OrdinalData+  PhoneNumber :: Dimension PhoneNumberData+  Quantity :: Dimension QuantityData+  Temperature :: Dimension TemperatureData+  Time :: Dimension TimeData+  TimeGrain :: Dimension Grain+  Url :: Dimension UrlData+  Volume :: Dimension VolumeData++-- Show+instance Show (Dimension a) where+  show RegexMatch = "RegexMatch"+  show Distance = "Distance"+  show Duration = "Duration"+  show Email = "Email"+  show AmountOfMoney = "AmountOfMoney"+  show Numeral = "Numeral"+  show Ordinal = "Ordinal"+  show PhoneNumber = "PhoneNumber"+  show Quantity = "Quantity"+  show Temperature = "Temperature"+  show Time = "Time"+  show TimeGrain = "TimeGrain"+  show Url = "Url"+  show Volume = "Volume"+instance GShow Dimension where gshowsPrec = showsPrec++-- TextShow+instance TextShow (Dimension a) where+  showb d = TS.fromString $ show d+instance TextShow (Some Dimension) where+  showb (This d) = showb d++-- Hashable+instance Hashable (Some Dimension) where+  hashWithSalt s (This a) = hashWithSalt s a+instance Hashable (Dimension a) where+  hashWithSalt s RegexMatch  = hashWithSalt s (0::Int)+  hashWithSalt s Distance    = hashWithSalt s (1::Int)+  hashWithSalt s Duration    = hashWithSalt s (2::Int)+  hashWithSalt s Email       = hashWithSalt s (3::Int)+  hashWithSalt s AmountOfMoney     = hashWithSalt s (4::Int)+  hashWithSalt s Numeral     = hashWithSalt s (5::Int)+  hashWithSalt s Ordinal     = hashWithSalt s (6::Int)+  hashWithSalt s PhoneNumber = hashWithSalt s (7::Int)+  hashWithSalt s Quantity    = hashWithSalt s (8::Int)+  hashWithSalt s Temperature = hashWithSalt s (9::Int)+  hashWithSalt s Time        = hashWithSalt s (10::Int)+  hashWithSalt s TimeGrain   = hashWithSalt s (11::Int)+  hashWithSalt s Url         = hashWithSalt s (12::Int)+  hashWithSalt s Volume      = hashWithSalt s (13::Int)+++toName :: Dimension a -> Text+toName RegexMatch = "regex"+toName Distance = "distance"+toName Duration = "duration"+toName Email = "email"+toName AmountOfMoney = "amount-of-money"+toName Numeral = "number"+toName Ordinal = "ordinal"+toName PhoneNumber = "phone-number"+toName Quantity = "quantity"+toName Temperature = "temperature"+toName Time = "time"+toName TimeGrain = "time-grain"+toName Url = "url"+toName Volume = "volume"++fromName :: Text -> Maybe (Some 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)+      ]++instance GEq Dimension where+  geq RegexMatch RegexMatch = Just Refl+  geq RegexMatch _ = Nothing+  geq Distance Distance = Just Refl+  geq Distance _ = Nothing+  geq Duration Duration = Just Refl+  geq Duration _ = Nothing+  geq Email Email = Just Refl+  geq Email _ = Nothing+  geq AmountOfMoney AmountOfMoney = Just Refl+  geq AmountOfMoney _ = Nothing+  geq Numeral Numeral = Just Refl+  geq Numeral _ = Nothing+  geq Ordinal Ordinal = Just Refl+  geq Ordinal _ = Nothing+  geq PhoneNumber PhoneNumber = Just Refl+  geq PhoneNumber _ = Nothing+  geq Quantity Quantity = Just Refl+  geq Quantity _ = Nothing+  geq Temperature Temperature = Just Refl+  geq Temperature _ = Nothing+  geq Time Time = Just Refl+  geq Time _ = Nothing+  geq TimeGrain TimeGrain = Just Refl+  geq TimeGrain _ = Nothing+  geq Url Url = Just Refl+  geq Url _ = Nothing+  geq Volume Volume = Just Refl+  geq Volume _ = Nothing
+ Duckling/Dimensions/UK.hs view
@@ -0,0 +1,19 @@+-- 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.UK+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Numeral+  , This Ordinal+  ]
+ Duckling/Dimensions/VI.hs view
@@ -0,0 +1,21 @@+-- 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.VI+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Time+  ]
+ Duckling/Dimensions/ZH.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++module Duckling.Dimensions.ZH+  ( allDimensions+  ) where++import Duckling.Dimensions.Types++allDimensions :: [Some Dimension]+allDimensions =+  [ This Duration+  , This Numeral+  , This Ordinal+  , This Temperature+  , This Time+  ]
+ Duckling/Distance/EN/Corpus.hs view
@@ -0,0 +1,43 @@+-- 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.Distance.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilometers"+             , "3 km"+             , "3km"+             , "3k"+             , "3.0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 miles"+             , "eight mile"+             ]+  , examples (DistanceValue M 9)+             [ "9m"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centimeters"+             ]+  ]
+ Duckling/Distance/EN/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.EN.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.Types++ruleDistanceFeetInch :: Rule+ruleDistanceFeetInch = Rule+  { name = "<distance|feet> <distance|inch>"+  , pattern =+    [ unitDistance TDistance.Foot+    , unitDistance TDistance.Inch+    ]+  , prod = \tokens -> case tokens of+      (Token Distance DistanceData {TDistance.value = feet}:+       Token Distance DistanceData {TDistance.value = inches}:+       _) -> Just . Token Distance . withUnit TDistance.Inch . distance $+        feet * 12 + inches+      _ -> Nothing+  }++ruleDistanceFeetAndInch :: Rule+ruleDistanceFeetAndInch = Rule+  { name = "<distance|feet> and <distance|inch>"+  , pattern =+    [ unitDistance TDistance.Foot+    , regex "and"+    , unitDistance TDistance.Inch+    ]+  , prod = \tokens -> case tokens of+      (Token Distance DistanceData {TDistance.value = feet}:+       _:+       Token Distance DistanceData {TDistance.value = inches}:+       _) -> Just . Token Distance . withUnit TDistance.Inch . distance $+        feet * 12 + inches+      _ -> Nothing+  }++distances :: [(Text, String, TDistance.Unit)]+distances = [ ("<latent dist> km", "k(ilo)?m?(eter)?s?", TDistance.Kilometre)+            , ("<latent dist> feet", "('|f(oo|ee)?ts?)", TDistance.Foot)+            , ("<latent dist> inch", "(''|inch(es)?)", TDistance.Inch)+            , ("<latent dist> yard", "y(ar)?ds?", TDistance.Yard)+            , ("<dist> meters", "meters?", TDistance.Metre)+            , ("<dist> centimeters", "cm|centimeters?", TDistance.Centimetre)+            , ("<dist> miles", "miles?", TDistance.Mile)+            , ("<dist> m (ambiguous miles or meters)", "m", TDistance.M)+            ]++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 =+  [ ruleDistanceFeetInch+  , ruleDistanceFeetAndInch+  ]+  ++ ruleDistances
+ Duckling/Distance/ES/Corpus.hs view
@@ -0,0 +1,48 @@+-- 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.Distance.ES.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ES}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilómetros"+             , "3 kilometros"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3,0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 miles"+             ]+  , examples (DistanceValue Metre 9)+             [ "9m"+             , "9 metros"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centímetros"+             ]+  ]
+ Duckling/Distance/ES/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.ES.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "k(il(\x00f3|o))?m?(etro)?s?"+    ]+  , 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 "m(etros?)?"+    ]+  , 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|cent(\x00ed|i)m(etros?))"+    ]+  , 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 "miles?"+    ]+  , 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/FR/Corpus.hs view
@@ -0,0 +1,48 @@+-- 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.Distance.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilomètres"+             , "3 kilometres"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3,0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 miles"+             ]+  , examples (DistanceValue Metre 9)+             [ "9 metres"+             , "9m"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centimetres"+             ]+  ]
+ Duckling/Distance/FR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.FR.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "k(ilo)?m?((e|\x00e9|\x00e8)tre)?s?"+    ]+  , 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 "m((e|\x00e9|\x00e8)tres?)?"+    ]+  , 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|centim(e|\x00e9|\x00e8)tres?"+    ]+  , 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 "miles?"+    ]+  , 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/GA/Corpus.hs view
@@ -0,0 +1,47 @@+-- 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.Distance.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 ciliméadair"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3.0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 mhíle"+             , "8 míle"+             ]+  , examples (DistanceValue M 9)+             [ "9m"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 cheintiméadar"+             ]+  ]
+ Duckling/Distance/GA/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.GA.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleDistMeters :: Rule+ruleDistMeters = Rule+  { name = "<dist> meters"+  , pattern =+    [ dimension Distance+    , regex "mh?(e|\x00e9)adai?r"+    ]+  , 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 "(c\\.?m\\.?|g?ch?eintimh?(e|\x00e9)adai?r)"+    ]+  , 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 "mh?(\x00ed|i)lt?e"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Mile dd+      _ -> Nothing+  }++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "(k\\.?(m\\.?)?|g?ch?ilim(e|\x00e9)adai?r)"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Kilometre dd+      _ -> Nothing+  }++ruleLatentDistTroigh :: Rule+ruleLatentDistTroigh = Rule+  { name = "<latent dist> troigh"+  , pattern =+    [ dimension Distance+    , regex "('|d?th?roi[tg]he?|tr\\.?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Foot dd+      _ -> Nothing+  }++ruleLatentDistOrlach :: Rule+ruleLatentDistOrlach = Rule+  { name = "<latent dist> orlach"+  , pattern =+    [ dimension Distance+    , regex "(''|([nth]-?)?orl(ach|aigh|a(\x00ed|i)|\\.))"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Inch dd+      _ -> Nothing+  }++ruleDistMAmbiguousMilesOrMeters :: Rule+ruleDistMAmbiguousMilesOrMeters = Rule+  { name = "<dist> m (ambiguous miles or meters)"+  , pattern =+    [ dimension Distance+    , regex "m"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.M dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDistCentimeters+  , ruleDistMAmbiguousMilesOrMeters+  , ruleDistMeters+  , ruleDistMiles+  , ruleLatentDistKm+  , ruleLatentDistOrlach+  , ruleLatentDistTroigh+  ]
+ Duckling/Distance/HR/Corpus.hs view
@@ -0,0 +1,45 @@+-- 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.Distance.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilometra"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3,0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 milja"+             ]+  , examples (DistanceValue M 9)+             [ "9m"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centimetra"+             ]+  ]
+ Duckling/Distance/HR/Rules.hs view
@@ -0,0 +1,92 @@+-- 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 #-}++module Duckling.Distance.HR.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 "k(ilo)?m?(eta?r)?a?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Kilometre dd+      _ -> Nothing+  }++ruleDistMetar :: Rule+ruleDistMetar = Rule+  { name = "<dist> metar"+  , pattern =+    [ dimension Distance+    , regex "metara?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Metre dd+      _ -> Nothing+  }++ruleDistCentimetar :: Rule+ruleDistCentimetar = Rule+  { name = "<dist> centimetar"+  , pattern =+    [ dimension Distance+    , regex "cm|centimeta?ra?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Centimetre dd+      _ -> Nothing+  }++ruleDistMilja :: Rule+ruleDistMilja = Rule+  { name = "<dist> milja"+  , pattern =+    [ dimension Distance+    , regex "milja"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) -> Just . Token Distance $ withUnit TDistance.Mile dd+      _ -> Nothing+  }++ruleDistMAmbiguousMilesOrMeters :: Rule+ruleDistMAmbiguousMilesOrMeters = Rule+  { name = "<dist> m (ambiguous miles or meters)"+  , pattern =+    [ dimension Distance+    , regex "m"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) -> Just . Token Distance $ withUnit TDistance.M dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDistCentimetar+  , ruleDistMAmbiguousMilesOrMeters+  , ruleDistMetar+  , ruleDistMilja+  , ruleLatentDistKm+  ]
+ Duckling/Distance/Helpers.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.Helpers+  ( distance+  , unitDistance+  , withUnit+  ) where+++import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Types (DistanceData(..))+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++-- -----------------------------------------------------------------+-- Patterns++unitDistance :: TDistance.Unit -> PatternItem+unitDistance value = Predicate $ \x -> case x of+  (Token Distance DistanceData {TDistance.unit = Just unit}) -> value == unit+  _ -> False++-- -----------------------------------------------------------------+-- Production++distance :: Double -> DistanceData+distance x = DistanceData {TDistance.value = x, TDistance.unit = Nothing}++withUnit :: TDistance.Unit -> DistanceData -> DistanceData+withUnit value dd = dd {TDistance.unit = Just value}
+ Duckling/Distance/KO/Corpus.hs view
@@ -0,0 +1,56 @@+-- 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.Distance.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 킬로미터"+             , "3 킬로"+             , "3 키로"+             , "3 km"+             , "3km"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3.0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 miles"+             , "8 마일"+             , "8 마일즈"+             ]+  , examples (DistanceValue Metre 9)+             [ "9m"+             , "9미터"+             , "9메터"+             , "구메터"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 센치"+             , "이센치"+             , "2 센티"+             , "2 센티미터"+             , "2 센치미터"+             ]+  ]
+ Duckling/Distance/KO/Rules.hs view
@@ -0,0 +1,154 @@+-- 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 #-}++module Duckling.Distance.KO.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleLatentDistYard :: Rule+ruleLatentDistYard = Rule+  { name = "<latent dist> yard"+  , pattern =+    [ dimension Distance+    , regex "y(ar)?ds?|\xc57c\xb4dc"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Yard dd+      _ -> Nothing+  }++ruleDistCentimeters :: Rule+ruleDistCentimeters = Rule+  { name = "<dist> centimeters"+  , pattern =+    [ dimension Distance+    , regex "cm|\xc13c(\xd2f0|\xce58)((\xbbf8|\xba54)\xd130)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Centimetre dd+      _ -> Nothing+  }++ruleLatentDistFeetAndLatentDistInch :: Rule+ruleLatentDistFeetAndLatentDistInch = Rule+  { name = "<latent dist> feet and <latent dist> inch "+  , pattern =+    [ dimension Distance+    , regex "('|f(oo|ee)?ts?)|\xd53c\xd2b8"+    , dimension Distance+    , regex "(''|inch(es)?)|\xc778\xce58"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Foot dd+      _ -> Nothing+  }++ruleDistMeters :: Rule+ruleDistMeters = Rule+  { name = "<dist> meters"+  , pattern =+    [ dimension Distance+    , regex "m|(\xbbf8|\xba54|\xb9e4)\xd130"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Metre dd+      _ -> Nothing+  }++ruleLatentDistFeet :: Rule+ruleLatentDistFeet = Rule+  { name = "<latent dist> feet"+  , pattern =+    [ dimension Distance+    , regex "('|f(oo|ee)?ts?)|\xd53c\xd2b8"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Foot dd+      _ -> Nothing+  }++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "km|(\xd0ac|\xd0a4)\xb85c((\xbbf8|\xba54)\xd130)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Kilometre dd+      _ -> Nothing+  }++ruleHalf :: Rule+ruleHalf = Rule+  { name = "half"+  , pattern =+    [ regex "\xbc18"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:_) ->+        Just . Token Distance $ distance v+      _ -> Nothing+  }++ruleDistMiles :: Rule+ruleDistMiles = Rule+  { name = "<dist> miles"+  , pattern =+    [ dimension Distance+    , regex "miles?|\xb9c8\xc77c(\xc988)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Mile dd+      _ -> Nothing+  }++ruleLatentDistInch :: Rule+ruleLatentDistInch = Rule+  { name = "<latent dist> inch"+  , pattern =+    [ dimension Distance+    , regex "(''|inch(es)?)|\xc778\xce58"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Inch dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDistCentimeters+  , ruleDistMeters+  , ruleDistMiles+  , ruleHalf+  , ruleLatentDistFeet+  , ruleLatentDistFeetAndLatentDistInch+  , ruleLatentDistInch+  , ruleLatentDistKm+  , ruleLatentDistYard+  ]
+ Duckling/Distance/NL/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.NL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilometer"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3,0 km"+             , "3,0km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 mijl"+             ]+  , examples (DistanceValue Metre 9)+             [ "9m"+             , "9 m"+             , "9 meter"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 cm"+             , "2 centimeter"+             ]+  ]
+ Duckling/Distance/NL/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.NL.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "k(ilo)?m?(eter)?s?"+    ]+  , 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 "m(eter)?"+    ]+  , 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 "(c(enti)?m(eter)?s?)"+    ]+  , 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 "mijl?"+    ]+  , 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/PT/Corpus.hs view
@@ -0,0 +1,48 @@+-- 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.Distance.PT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilómetros"+             , "3 kilometros"+             , "3 km"+             , "3km"+             , "3k"+             ]+  , examples (DistanceValue Kilometre 3.0)+             [ "3,0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 milhas"+             ]+  , examples (DistanceValue Metre 9)+             [ "9m"+             , "9 metros"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centímetros"+             ]+  ]
+ Duckling/Distance/PT/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.PT.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "k(il(\x00f3|o))?m?(etro)?s?"+    ]+  , 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 "m(etros?)?"+    ]+  , 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|cent(\x00ed|i)m(etros?))"+    ]+  , 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 "milhas?"+    ]+  , 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/RO/Corpus.hs view
@@ -0,0 +1,47 @@+-- 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.Distance.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Distance.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DistanceValue Kilometre 3)+             [ "3 kilometri"+             , "3 km"+             , "3km"+             , "3,0 km"+             ]+  , examples (DistanceValue Mile 8)+             [ "8 mile"+             ]+  , examples (DistanceValue Metre 9)+             [ "9m"+             , "9 m"+             ]+  , examples (DistanceValue Centimetre 2)+             [ "2cm"+             , "2 centimetri"+             ]+  , examples (DistanceValue Foot 10)+             [ "zece picioare"+             ]+  ]
+ Duckling/Distance/RO/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.RO.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import qualified Duckling.Distance.Types as TDistance+import Duckling.Types++ruleLatentDistKm :: Rule+ruleLatentDistKm = Rule+  { name = "<latent dist> km"+  , pattern =+    [ dimension Distance+    , regex "(kilometr[iu]|km)"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Kilometre dd+      _ -> Nothing+  }++ruleLatentDistPicioare :: Rule+ruleLatentDistPicioare = Rule+  { name = "<latent dist> picioare"+  , pattern =+    [ dimension Distance+    , regex "(picio(are|r))"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Foot dd+      _ -> Nothing+  }++ruleLatentDistInch :: Rule+ruleLatentDistInch = Rule+  { name = "<latent dist> inch"+  , pattern =+    [ dimension Distance+    , regex "(inch|inci|inchi)"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Inch dd+      _ -> Nothing+  }++ruleLatentDistYarzi :: Rule+ruleLatentDistYarzi = Rule+  { name = "<latent dist> yarzi"+  , pattern =+    [ dimension Distance+    , regex "y(ar)?(zi|d)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Yard dd+      _ -> Nothing+  }++ruleDistMeters :: Rule+ruleDistMeters = Rule+  { name = "<dist> meters"+  , pattern =+    [ dimension Distance+    , regex "(metr[ui]|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 "(centimetr[iu]|cm)"+    ]+  , 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 "mil(e|a|\x0103)"+    ]+  , prod = \tokens -> case tokens of+      (Token Distance dd:_) ->+        Just . Token Distance $ withUnit TDistance.Mile dd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDistCentimeters+  , ruleDistMeters+  , ruleDistMiles+  , ruleLatentDistInch+  , ruleLatentDistKm+  , ruleLatentDistPicioare+  , ruleLatentDistYarzi+  ]
+ Duckling/Distance/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Distance.Rules+  ( rules+  ) where+++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Distance.Helpers+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleNumeralAsDistance :: Rule+ruleNumeralAsDistance = Rule+  { name = "number as distance"+  , pattern =+    [ dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:_) ->+        Just . Token Distance $ distance v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralAsDistance+  ]
+ Duckling/Distance/Types.hs view
@@ -0,0 +1,65 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Distance.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 Unit+  = Foot+  | Centimetre+  | Kilometre+  | Inch+  | M -- ambiguous between Mile and Metre+  | Metre+  | Mile+  | Yard+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance ToJSON Unit where+  toJSON = String . Text.toLower . Text.pack . show++data DistanceData = DistanceData+  { unit :: Maybe Unit+  , value :: Double+  }+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve DistanceData where+  type ResolvedValue DistanceData = DistanceValue+  resolve _ DistanceData {unit = Nothing} = Nothing+  resolve _ DistanceData {unit = Just unit, value} =+    Just DistanceValue {vValue = value, vUnit = unit}++data DistanceValue = DistanceValue+  { vUnit :: Unit+  , vValue :: Double+  }+  deriving (Eq, Ord, Show)++instance ToJSON DistanceValue where+  toJSON (DistanceValue unit value) = object+    [ "type" .= ("value" :: Text)+    , "value" .= value+    , "unit" .= unit+    ]
+ Duckling/Duration/DA/Rules.hs view
@@ -0,0 +1,142 @@+-- 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 #-}++module Duckling.Duration.DA.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 (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "pr(\x00e6)cis"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      -- TODO(jodent) +precision exact+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "og (en )?halv timer?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleAUnitofduration :: Rule+ruleAUnitofduration = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ regex "en|et?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex "mere|mindre"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleFortnight :: Rule+ruleFortnight = Rule+  { name = "fortnight"+  , pattern =+    [ regex "(a|one)? fortnight"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(omkring|cirka|ca.)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      -- TODO(jodent) +precision approximate+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\,(\\d+)"+    , regex "timer?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2|en halv) time"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++rules :: [Rule]+rules =+  [ ruleAUnitofduration+  , ruleAboutDuration+  , ruleExactlyDuration+  , ruleFortnight+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumeralnumberHours+  ]
+ Duckling/Duration/DE/Rules.hs view
@@ -0,0 +1,140 @@+-- 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 #-}++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 (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2\\s?|(einer )halbe?n? )stunde"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleFortnight :: Rule+ruleFortnight = Rule+  { name = "fortnight"+  , pattern =+    [ regex "(a|one)? fortnight"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , regex "mehr|weniger"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       _:+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+) stunden?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "ein ?halb stunden?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleAUnitofduration :: Rule+ruleAUnitofduration = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ regex "eine?(r|n)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "ungef\x00e4hr|zirka"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "genau|exakt"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAUnitofduration+  , ruleAboutDuration+  , ruleExactlyDuration+  , ruleFortnight+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumeralnumberHours+  ]
+ Duckling/Duration/EN/Corpus.hs view
@@ -0,0 +1,65 @@+-- 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.Duration.EN.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext, examples)+  where+    examples =+      [ "for months"+      , "in days"+      , "secretary"+      , "minutes"+      , "I second that"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "one sec"+             , "1 second"+             , "1\""+             ]+  , examples (DurationData 2 Minute)+             [ "2 mins"+             , "two minutes"+             , "2'"+             ]+  , examples (DurationData 30 Day)+             [ "30 days"+             ]+  , examples (DurationData 7 Week)+             [ "seven weeks"+             ]+  , examples (DurationData 1 Month)+             [ "1 month"+             , "a month"+             ]+  , examples (DurationData 3 Quarter)+             [ "3 quarters"+             ]+  , examples (DurationData 2 Year)+             [ "2 years"+             ]+  ]
+ Duckling/Duration/EN/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.EN.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 (parseInt)+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleDurationQuarterOfAnHour :: Rule+ruleDurationQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern = [ regex "(1/4\\s?h(our)?|(a\\s)?quarter of an hour)" ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleDurationHalfAnHour :: Rule+ruleDurationHalfAnHour = Rule+  { name = "half an hour"+  , pattern = [regex "(1/2\\s?h(our)?|half an? hour)"]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleDurationThreeQuartersOfAnHour :: Rule+ruleDurationThreeQuartersOfAnHour = Rule+  { name = "three-quarters of an hour"+  , pattern = [regex "(3/4\\s?h(our)?|three(\\s|-)quarters of an hour)"]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++ruleDurationFortnight :: Rule+ruleDurationFortnight = Rule+  { name = "fortnight"+  , pattern = [regex "(a|one)? fortnight"]+  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  }++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 TG.Minute $ floor v+         "\"" -> Just . Token Duration . duration TG.Second $ floor v+         _    -> Nothing+      _ -> Nothing+  }++ruleDurationNumeralMore :: Rule+ruleDurationNumeralMore = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , regex "more|less"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd:_:Token TimeGrain grain:_) ->+        Just . Token Duration . duration grain . floor $ TNumeral.value nd+      _ -> Nothing+  }++ruleDurationDotNumeralHours :: Rule+ruleDurationDotNumeralHours = Rule+  { name = "number.number hours"+  , pattern = [regex "(\\d+)\\.(\\d+) *hours?"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleDurationAndHalfHour :: Rule+ruleDurationAndHalfHour = Rule+  { name = "<integer> and an half hour"+  , pattern =+    [ Predicate isNatural+    , regex "and (an? )?half hours?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleDurationA :: Rule+ruleDurationA = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ regex "an?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleDurationPrecision :: Rule+ruleDurationPrecision = Rule+  { name = "about|exactly <duration>"+  , pattern =+    [ regex "(about|around|approximately|exactly)"+    , dimension Duration+    ]+    , prod = \tokens -> case tokens of+        (_:token:_) -> Just token+        _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDurationQuarterOfAnHour+  , ruleDurationHalfAnHour+  , ruleDurationThreeQuartersOfAnHour+  , ruleDurationFortnight+  , ruleDurationNumeralMore+  , ruleDurationDotNumeralHours+  , ruleDurationAndHalfHour+  , ruleDurationA+  , ruleDurationPrecision+  , ruleNumeralQuotes+  ]
+ Duckling/Duration/FR/Corpus.hs view
@@ -0,0 +1,66 @@+-- 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.Duration.FR.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext {lang = FR}, examples)+  where+    examples =+      [ "les jours"+      , "en secondaire"+      , "minutes"+      , "pendant des mois"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "une sec"+             , "1 seconde"+             , "1\""+             ]+  , examples (DurationData 2 Minute)+             [ "2 mins"+             , "deux minutes"+             , "2'"+             ]+  , examples (DurationData 30 Day)+             [ "30 jours"+             ]+  , examples (DurationData 7 Week)+             [ "sept semaines"+             ]+  , examples (DurationData 1 Month)+             [ "1 mois"+             , "un mois"+             ]+  , examples (DurationData 3 Quarter)+             [ "3 trimestres"+             ]+  , examples (DurationData 2 Year)+             [ "2 ans"+             ]+  ]
+ Duckling/Duration/FR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.FR.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++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 TG.Minute $ floor v+         "\"" -> Just . Token Duration . duration TG.Second $ floor v+         _    -> Nothing+      _ -> Nothing+  }++ruleUneUnitofduration :: Rule+ruleUneUnitofduration = Rule+  { name = "une <unit-of-duration>"+  , pattern =+    [ regex "une|la|le?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token TimeGrain grain:+       _) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleUnQuartDHeure :: Rule+ruleUnQuartDHeure = Rule+  { name = "un quart d'heure"+  , pattern =+    [ regex "(1/4\\s?h(eure)?|(un|1) quart d'heure)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleUneDemiHeure :: Rule+ruleUneDemiHeure = Rule+  { name = "une demi heure"+  , pattern =+    [ regex "(1/2\\s?h(eure)?|(1|une) demi(e)?(\\s|-)heure)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleTroisQuartsDHeure :: Rule+ruleTroisQuartsDHeure = Rule+  { name = "trois quarts d'heure"+  , pattern =+    [ regex "(3/4\\s?h(eure)?|(3|trois) quart(s)? d'heure)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++ruleDurationEnviron :: Rule+ruleDurationEnviron = Rule+  { name = "environ <duration>"+  , pattern =+    [ regex "environ"+    ]+    , prod = \tokens -> case tokens of+      -- TODO(jodent) +precision approximate+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleUneUnitofduration+  , ruleUnQuartDHeure+  , ruleUneDemiHeure+  , ruleTroisQuartsDHeure+  , ruleDurationEnviron+  , ruleNumeralQuotes+  ]
+ Duckling/Duration/GA/Corpus.hs view
@@ -0,0 +1,42 @@+-- 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.Duration.GA.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "aon soicind amhain"+             , "aon soicind"+             , "1 tshoicindi"+             , "1 tsoicind"+             ]+  , examples (DurationData 30 Minute)+             [ "leathuair"+             , "30 noimead"+             ]+  , examples (DurationData 14 Day)+             [ "coicís"+             ]+  ]
+ Duckling/Duration/GA/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.GA.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleCoics :: Rule+ruleCoics = Rule+  { name = "coicís"+  , pattern =+    [ regex "coic(\x00ed|i)s(\x00ed|i|e)?"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Day 14+  }++ruleLeathuair :: Rule+ruleLeathuair = Rule+  { name = "leathuair"+  , pattern =+    [ regex "leathuair(e|eanta)?"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleAonDurationAmhain :: Rule+ruleAonDurationAmhain = Rule+  { name = "aon X amhain"+  , pattern =+    [ isNumeralWith TNumeral.value (== 1)+    , dimension TimeGrain+    , isNumeralWith TNumeral.value (== 1)+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleIntegerUnitofdurationInteger :: Rule+ruleIntegerUnitofdurationInteger = Rule+  { name = "<unit-integer> <unit-of-duration> <tens-integer>"+  , pattern =+    [ isNumeralWith TNumeral.value (< 10)+    , dimension TimeGrain+    , isNumeralWith TNumeral.value (`elem` [10, 20 .. 50])+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token TimeGrain grain:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> Just . Token Duration . duration grain . floor $ v1 + v2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCoics+  , ruleIntegerUnitofdurationInteger+  , ruleLeathuair+  , ruleAonDurationAmhain+  ]
+ Duckling/Duration/HE/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.HE.Rules+  ( rules ) where++import Control.Monad (join)+import Data.Maybe+import Data.String+import Data.Text (Text)+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)+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++ruleQuarterOfAnHour :: Rule+ruleQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern =+    [ regex "(1/4/s \x05e9\x05e2\x05d4|\x05e8\x05d1\x05e2 \x05e9\x05e2\x05d4)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2/s \x05e9\x05e2\x05d4|\x05d7\x05e6\x05d9 \x05e9\x05e2\x05d4)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleThreequartersOfAnHour :: Rule+ruleThreequartersOfAnHour = Rule+  { name = "three-quarters of an hour"+  , pattern =+    [ regex "(3/4/s \x05e9\x05e2\x05d4|\x05e9\x05dc\x05d5\x05e9\x05ea \x05e8\x05d1\x05e2\x05d9 \x05e9\x05e2\x05d4)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++ruleNumbernumberHours :: Rule+ruleNumbernumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , regex "\x05e9\x05e2\x05d4|\x05e9\x05e2\x05d5\x05ea"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "\x05d5\x05d7\x05e6\x05d9 (\x05e9\x05e2\x05d5\x05ea|\x05e9\x05e2\x05d4)"+    ]+  , 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 "(\x05d1\x05e2\x05e8\x05da|\x05e1\x05d1\x05d9\x05d1\x05d5\x05ea|\x05d1\x05e7\x05d9\x05e8\x05d5\x05d1)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "\x05d1\x05d3\x05d9\x05d5\x05e7"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleNumbernumberHours+  , ruleQuarterOfAnHour+  , ruleThreequartersOfAnHour+  ]
+ Duckling/Duration/HR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.HR.Rules+  ( rules ) where++import Control.Monad (join)+import Data.Maybe+import Data.String+import Data.Text (Text)+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)+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++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "to(c|\x010d)no"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "i pol?a?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , regex "vi(s|\x0161)e|manje"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       _:+       Token TimeGrain grain:_) ->+         Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleQuarterOfAnHour :: Rule+ruleQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern =+    [ regex "((1/4|frtalj|kvarat|(c|\x010d)etvrt)\\s?(h|sata)?)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(oko|otprilike|odokativno)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleNumbernumberHours :: Rule+ruleNumbernumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , regex "sat(i|a)?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleThreequartersOfAnHour :: Rule+ruleThreequartersOfAnHour = Rule+  { name = "three-quarters of an hour"+  , pattern =+    [ regex "((3/4|tri-?frtalja|tri-?kvarat|tri-?(c|\x010d)etvrt(ine)?)\\s?(h|sata)?)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2\\s?(h|sata)?|pol?a? sata)"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++rules :: [Rule]+rules =+  [ ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumbernumberHours+  , ruleQuarterOfAnHour+  , ruleThreequartersOfAnHour+  ]
+ Duckling/Duration/Helpers.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.Helpers+  ( duration+  , isGrain+  , isNatural+  , isNumeralWith+  ) where++import Prelude++import Duckling.Dimensions.Types+import Duckling.Duration.Types (DurationData (DurationData))+import qualified Duckling.Duration.Types as TDuration+import Duckling.Numeral.Types (NumeralData (NumeralData))+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++-- -----------------------------------------------------------------+-- Patterns++isGrain :: TG.Grain -> Predicate+isGrain value (Token TimeGrain grain) = grain == value+isGrain _ _ = False++isNatural :: Predicate+isNatural (Token Numeral NumeralData {TNumeral.value = x}) =+  TNumeral.isNatural x+isNatural _ = False++isNumeralWith :: (NumeralData -> t) -> (t -> Bool) -> PatternItem+isNumeralWith f pred = Predicate $ \x -> case x of+  (Token Numeral x) -> pred $ f x+  _ -> False++-- -----------------------------------------------------------------+-- Production++duration :: TG.Grain -> Int -> DurationData+duration grain n = DurationData {TDuration.grain = grain, TDuration.value = n}
+ Duckling/Duration/IT/Rules.hs view
@@ -0,0 +1,68 @@+-- 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 #-}++module Duckling.Duration.IT.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleUneUnitofduration :: Rule+ruleUneUnitofduration = Rule+  { name = "une <unit-of-duration>"+  , pattern =+    [ regex "un[a']?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleUnQuartoDora :: Rule+ruleUnQuartoDora = Rule+  { name = "un quarto d'ora"+  , pattern =+    [ regex "un quarto d['i] ?ora"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleMezzOra :: Rule+ruleMezzOra = Rule+  { name = "mezz'ora"+  , pattern =+    [ regex "mezz[a'] ?ora"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleTreQuartiDora :: Rule+ruleTreQuartiDora = Rule+  { name = "tre quarti d'ora"+  , pattern =+    [ regex "(3|tre) quarti d['i] ?ora"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++rules :: [Rule]+rules =+  [ ruleUneUnitofduration+  , ruleUnQuartoDora+  , ruleMezzOra+  , ruleTreQuartiDora+  ]
+ Duckling/Duration/JA/Corpus.hs view
@@ -0,0 +1,40 @@+-- 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.Duration.JA.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = JA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 秒"+             , "一 秒間"+             ]+  , examples (DurationData 4 Minute)+             [ "四 分間"+             ]+  , examples (DurationData 100 Day)+             [ "百 日"+             , "百 日間"+             ]+  ]
+ Duckling/Duration/KO/Corpus.hs view
@@ -0,0 +1,40 @@+-- 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.Duration.KO.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 초"+             ]+  , examples (DurationData 30 Minute)+             [ "시간반"+             , "시반"+             , "서른분"+             ]+  , examples (DurationData 66 Minute)+             [ "1.1 시간"+             ]+  ]
+ Duckling/Duration/KO/Rules.hs view
@@ -0,0 +1,112 @@+-- 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 #-}++module Duckling.Duration.KO.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 (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ Predicate $ isGrain TG.Hour+    , regex "\xbc18"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleADay :: Rule+ruleADay = Rule+  { name = "a day - 하루"+  , pattern =+    [ regex "\xd558\xb8e8"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Day 1+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , regex "\xc2dc\xac04"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        hh <- parseInt m1+        dec <- parseInt m2+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length m2 - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "\xc2dc\xac04\xbc18"+    ]+  , 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 "\xb300\xcda9|\xc57d"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "\xc815\xd655\xd788"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleADay+  , ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleNumeralnumberHours+  ]
+ Duckling/Duration/NB/Corpus.hs view
@@ -0,0 +1,47 @@+-- 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.Duration.NB.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = NB}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 sek"+             , "en sek"+             , "ett sekund"+             , "e sekunder"+             ]+  , examples (DurationData 30 Minute)+             [ "tredve min"+             , "30 minutt"+             , "30 minutter"+             , "1/2 time"+             , "en halv time"+             ]+  , examples (DurationData 2 Day)+             [ "et par dager"+             , "2 dag"+             , "to dag"+             ]+  ]
+ Duckling/Duration/NB/Rules.hs view
@@ -0,0 +1,129 @@+-- 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 #-}++module Duckling.Duration.NB.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 (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2|en halv) time"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex "mere?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\,(\\d+) *timer?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration $ duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "og (en )?halv time?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleAUnitofduration :: Rule+ruleAUnitofduration = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ regex "en|ett|et?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(omkring|cirka|ca.|ca)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "(precis|akkurat)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAUnitofduration+  , ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumeralnumberHours+  ]
+ Duckling/Duration/PL/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.PL.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = PL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1s"+             , "1 sekund"+             , "jeden sekundzie"+             , "pojedynczy sekundach"+             ]+  , examples (DurationData 30 Minute)+             [ "pol godziny"+             , "pół godziny"+             , "30m"+             , "30 minut"+             , "trzydzieści minutami"+             ]+  , examples (DurationData 5 Day)+             [ "pięciu dniach"+             ]+  , examples (DurationData 100 Day)+             [ "sto dzień"+             , "setki dnią"+             ]+  ]
+ Duckling/Duration/PL/Rules.hs view
@@ -0,0 +1,131 @@+-- 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 #-}++module Duckling.Duration.PL.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 (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "p(o|\x00f3)(l|\x0142) godziny"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , regex "more|less"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       _:+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\.(\\d+)"+    , regex "godzin(y)?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "i (p(o|\x00f3)(l|\x0142)) godziny"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleUnitofdurationAsADuration :: Rule+ruleUnitofdurationAsADuration = Rule+  { name = "<unit-of-duration> as a duration"+  , pattern =+    [ dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(oko(l|\x0142)o|miej wi(\x0119|e)cej|jakie(s|\x015b))"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "r(o|\x00f3)wno|dok(l|\x0142)adnie"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumeralnumberHours+  , ruleUnitofdurationAsADuration+  ]
+ Duckling/Duration/PT/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.PT.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "um segundo"+             , "uma seg"+             ]+  , examples (DurationData 2 Minute)+             [ "duas mins"+             , "dois minutos"+             ]+  , examples (DurationData 20 Day)+             [ "20 dias"+             , "vinte días"+             ]+  ]
+ Duckling/Duration/RO/Corpus.hs view
@@ -0,0 +1,52 @@+-- 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.Duration.RO.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "o sec"+             , "1 secunda"+             ]+  , examples (DurationData 30 Minute)+             [ "jumatate ora"+             , "1/2h"+             , "treizeci minute"+             ]+  , examples (DurationData 45 Minute)+             [ "trei sferturi de oră"+             , "45min"+             ]+  , examples (DurationData 12 Week)+             [ "doișpe saptamanile"+             , "doisprezece saptămâni"+             ]+  , examples (DurationData 2 Month)+             [ "2 luni"+             ]+  , examples (DurationData 1 Quarter)+             [ "un trimestru"+             ]+  ]
+ Duckling/Duration/RO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.RO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleQuarterOfAnHour :: Rule+ruleQuarterOfAnHour = Rule+  { name = "quarter of an hour"+  , pattern =+    [ regex "(1/4\\s?(h|or(a|\x0103))|sfert de or(a|\x0103))"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 15+  }++ruleJumatateDeOra :: Rule+ruleJumatateDeOra = Rule+  { name = "jumatate de ora"+  , pattern =+    [ regex "(1/2\\s?(h|or(a|\x0103))|jum(a|\x0103)tate (de )?or(a|\x0103))"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleTreiSferturiDeOra :: Rule+ruleTreiSferturiDeOra = Rule+  { name = "trei sferturi de ora"+  , pattern =+    [ regex "(3/4\\s?(h|or(a|\x0103))|trei sferturi de or(a|\x0103))"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 45+  }++ruleOUnitofduration :: Rule+ruleOUnitofduration = Rule+  { name = "o <unit-of-duration>"+  , pattern =+    [ regex "o|un"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleExactInJurDeDuration :: Rule+ruleExactInJurDeDuration = Rule+  { name = "exact|in jur de <duration>"+  , pattern =+    [ regex "(exact|aproximativ|(i|\x00ee)n jur de)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleExactInJurDeDuration+  , ruleJumatateDeOra+  , ruleOUnitofduration+  , ruleQuarterOfAnHour+  , ruleTreiSferturiDeOra+  ]
+ Duckling/Duration/Rules.hs view
@@ -0,0 +1,42 @@+-- 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 #-}++module Duckling.Duration.Rules+  ( rules+  ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleIntegerUnitofduration :: Rule+ruleIntegerUnitofduration = Rule+  { name = "<integer> <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntegerUnitofduration+  ]
+ Duckling/Duration/SV/Corpus.hs view
@@ -0,0 +1,48 @@+-- 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.Duration.SV.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext {lang = SV}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "enkel sek"+             , "1 sekund fler"+             , "1 sekunder mer"+             , "en sekunderna"+             , "et sek"+             , "ett sek"+             ]+  , examples (DurationData 30 Minute)+             [ "1/2 timme"+             , "en halv timme"+             , "0,5 timmar"+             , "30 minuterna"+             , "trettio min"+             ]+  , examples (DurationData 5 Year)+             [ "5 år"+             , "fem år"+             ]+  ]
+ Duckling/Duration/SV/Rules.hs view
@@ -0,0 +1,131 @@+-- 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 #-}++module Duckling.Duration.SV.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 (parseInt)+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleHalfAnHour :: Rule+ruleHalfAnHour = Rule+  { name = "half an hour"+  , pattern =+    [ regex "(1/2|en halv) timme"+    ]+  , prod = \_ -> Just . Token Duration $ duration TG.Minute 30+  }++ruleIntegerMoreUnitofduration :: Rule+ruleIntegerMoreUnitofduration = Rule+  { name = "<integer> more <unit-of-duration>"+  , pattern =+    [ Predicate isNatural+    , dimension TimeGrain+    , regex "fler|mer"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token TimeGrain grain:+       _) -> Just . Token Duration . duration grain $ floor v+      _ -> Nothing+  }++ruleNumeralnumberHours :: Rule+ruleNumeralnumberHours = Rule+  { name = "number.number hours"+  , pattern =+    [ regex "(\\d+)\\,(\\d+)"+    , regex "timm(e|ar)?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:d:_)):_) -> do+        hh <- parseInt h+        dec <- parseInt d+        let divisor = floor $ (fromIntegral (10 :: Integer) :: Float) **+                        fromIntegral (Text.length d - 1)+            numerator = fromIntegral $ 6 * dec+        Just . Token Duration . duration TG.Minute $+          60 * hh + quot numerator divisor+      _ -> Nothing+  }++ruleIntegerAndAnHalfHours :: Rule+ruleIntegerAndAnHalfHours = Rule+  { name = "<integer> and an half hours"+  , pattern =+    [ Predicate isNatural+    , regex "och (en )?halv timme?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . Token Duration . duration TG.Minute $ 30 + 60 * floor v+      _ -> Nothing+  }++ruleAUnitofduration :: Rule+ruleAUnitofduration = Rule+  { name = "a <unit-of-duration>"+  , pattern =+    [ regex "en|ett?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        Just . Token Duration $ duration grain 1+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(omkring|cirka|ca.|ca|runt)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleExactlyDuration :: Rule+ruleExactlyDuration = Rule+  { name = "exactly <duration>"+  , pattern =+    [ regex "(precis|exakt)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAUnitofduration+  , ruleAboutDuration+  , ruleExactlyDuration+  , ruleHalfAnHour+  , ruleIntegerAndAnHalfHours+  , ruleIntegerMoreUnitofduration+  , ruleNumeralnumberHours+  ]
+ Duckling/Duration/Types.hs view
@@ -0,0 +1,48 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Duration.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Text (Text)+import GHC.Generics+import TextShow (showt)+import Prelude++import Duckling.Resolve (Resolve(..))+import Duckling.TimeGrain.Types (Grain(..), inSeconds)++data DurationData = DurationData+  { value :: Int+  , grain :: Grain+  }+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++instance Resolve DurationData where+  type ResolvedValue DurationData = DurationData+  resolve _ x = Just x++instance ToJSON DurationData where+  toJSON DurationData {value, grain} = object+    [ "value"      .= value+    , "unit"       .= grain+    , showt grain  .= value+    , "normalized" .= object+      [ "unit"  .= ("second" :: Text)+      , "value" .= inSeconds grain value+      ]+    ]
+ Duckling/Duration/ZH/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Duration.ZH.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Duration.Types+import Duckling.Testing.Types+import Duckling.TimeGrain.Types (Grain(..))++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (DurationData 1 Second)+             [ "1 秒钟"+             , "一 秒鐘"+             ]+  , examples (DurationData 5 Day)+             [ "5 天"+             , "五 天"+             ]+  , examples (DurationData 10 Month)+             [ "10 月"+             , "十 月"+             ]+  ]
+ Duckling/Email/Corpus.hs view
@@ -0,0 +1,47 @@+-- 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.Email.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Email.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext, examples)+  where+    examples =+      [ "hey@6"+      , "hey@you"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (EmailData "alice@exAmple.io")+             [ "alice@exAmple.io"+             ]+  , examples (EmailData "yo+yo@blah.org")+             [ "yo+yo@blah.org"+             ]+  , examples (EmailData "1234+abc@x.net")+             [ "1234+abc@x.net"+             ]+  , examples (EmailData "jean-jacques@stuff.co.uk")+             [ "jean-jacques@stuff.co.uk"+             ]+  ]
+ Duckling/Email/EN/Corpus.hs view
@@ -0,0 +1,38 @@+-- 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.Email.EN.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Email.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, 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"+             ]+  ]
+ Duckling/Email/EN/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Email.EN.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\\._+-]+) at ([\\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/FR/Corpus.hs view
@@ -0,0 +1,40 @@+-- 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.Email.FR.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Email.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (EmailData "alice@exAmple.io")+             [ "alice arobase exAmple.io"+             ]+  , examples (EmailData "yo+yo@blah.org")+             [ "yo+yo arobase blah.org"+             ]+  , examples (EmailData "1234+abc@x.net")+             [ "1234+abc arobase x.net"+             ]+  , examples (EmailData "jean-jacques@stuff.co.uk")+             [ "jean-jacques arobase stuff.co.uk"+             ]+  ]
+ Duckling/Email/FR/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Email.FR.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\\._+-]+) arobase ([\\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
@@ -0,0 +1,40 @@+-- 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.Email.IT.Corpus+  ( corpus+  ) where++import Data.String+import Prelude++import Duckling.Email.Types+import Duckling.Lang+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = IT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (EmailData "alice@exAmple.io")+             [ "alice chiocciola exAmple.io"+             ]+  , examples (EmailData "yo+yo@blah.org")+             [ "yo+yo chiocciola blah.org"+             ]+  , examples (EmailData "1234+abc@x.net")+             [ "1234+abc chiocciola x.net"+             ]+  , examples (EmailData "jean-jacques@stuff.co.uk")+             [ "jean-jacques chiocciola stuff.co.uk"+             ]+  ]
+ Duckling/Email/IT/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Email.IT.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\\._+-]+) chiocciola ([\\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/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Email.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Email.Types (EmailData (..))+import qualified Duckling.Email.Types as TEmail+import Duckling.Regex.Types+import Duckling.Types++ruleEmail :: Rule+ruleEmail = Rule+  { name = "email"+  , pattern =+    [ regex "([\\w\\._+-]+@[\\w_-]+(\\.[\\w_-]+)+)"+    ]+  , prod = \xs -> case xs of+      (Token RegexMatch (GroupMatch (x:_)):_) ->+        Just $ Token Email EmailData {TEmail.value = x}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleEmail+  ]
+ Duckling/Email/Types.hs view
@@ -0,0 +1,35 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Email.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Text (Text)+import GHC.Generics+import Prelude++import Duckling.Resolve (Resolve(..))++newtype EmailData = EmailData { value :: Text }+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve EmailData where+  type ResolvedValue EmailData = EmailData+  resolve _ x = Just x++instance ToJSON EmailData where+  toJSON EmailData {value} = object [ "value" .= value ]
+ Duckling/Engine.hs view
@@ -0,0 +1,228 @@+-- 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 NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Engine+  ( parseAndResolve+  , lookupRegexAnywhere+  , runDuckling+  ) where++import Control.DeepSeq+import Control.Monad.Extra+import Data.Aeson+import qualified Data.Array as Array+import Data.ByteString (ByteString)+import Data.Functor.Identity+import qualified Data.Foldable as Foldable+import Data.Maybe+import Data.Text (Text)+import qualified Data.List as L+import Prelude+import qualified Text.Regex.PCRE as PCRE++import Duckling.Dimensions.Types+import qualified Duckling.Engine.Regex as Regex+import Duckling.Regex.Types+import Duckling.Resolve+import Duckling.Types+import qualified Duckling.Types.Document as Document+import Duckling.Types.Document (Document)+import qualified Duckling.Types.Stash as Stash+import Duckling.Types.Stash (Stash)++-- -----------------------------------------------------------------+-- Engine++type Duckling a = Identity a++runDuckling :: Duckling a -> a+runDuckling ma = runIdentity ma++parseAndResolve :: [Rule] -> Text -> Context -> [ResolvedToken]+parseAndResolve rules input context = mapMaybe (resolveNode context) .+  force $ Stash.toPosOrderedList $ runDuckling $+  parseString rules (Document.fromText input)++produce :: Match -> Maybe Node+produce (_, _, []) = Nothing+produce (Rule name _ production, _, etuor@(Node {nodeRange = Range _ e}:_)) = do+  let route = reverse etuor+  token <- force $ production $ map token route+  case route of+    (Node {nodeRange = Range p _}:_) -> Just Node+      { nodeRange = Range p e+      , token = token+      , children = route+      , rule = Just name+      }+    [] -> Nothing++-- | Handle a regex match at a given position+lookupRegex :: Document -> PCRE.Regex -> Int -> Duckling [Node]+lookupRegex doc _regex position | position >= Document.length doc = return []+lookupRegex doc regex position =+  lookupRegexCommon doc regex position Regex.matchOnce++-- | Handle a regex match anywhere in the text+lookupRegexAnywhere :: Document -> PCRE.Regex -> Duckling [Node]+lookupRegexAnywhere doc regex = lookupRegexCommon doc regex 0 Regex.matchAll++{-# INLINE lookupRegexCommon #-}+-- INLINE bloats the code a bit, but the code is better+lookupRegexCommon+  :: Foldable t+  => Document+  -> PCRE.Regex+  -> Int+  -> (PCRE.Regex -> ByteString -> t PCRE.MatchArray)+  -> Duckling [Node]+lookupRegexCommon doc regex position matchFun = return nodes+  where+  -- See Note [Regular expressions and Text] to understand what's going+  -- on here+  (substring, rangeToText, translateRange) =+    Document.byteStringFromPos doc position+  nodes = mapMaybe (f . Array.elems) $ Foldable.toList $+    matchFun regex substring+  f :: [(Int, Int)] -> Maybe Node+  f [] = Nothing+  f ((0,0):_) = Nothing+  f ((bsStart, bsLen):groups) =+    if Document.isRangeValid doc start end+      then Just node+      else Nothing+    where+    textGroups = map rangeToText groups+    (start, end) = translateRange bsStart bsLen+    node = Node+      { nodeRange = Range start end+      , token = Token RegexMatch (GroupMatch textGroups)+      , children = []+      , rule = Nothing+      }++-- | Handle one PatternItem at a given position+lookupItem :: Document -> PatternItem -> Stash -> Int -> Duckling [Node]+lookupItem doc (Regex re) _ position =+  filter (isPositionValid position doc) <$>+  lookupRegex doc re position+lookupItem doc (Predicate p) stash position =+  return $+  filter (p . token) $+  takeWhile (isPositionValid position doc) $+  Stash.toPosOrderedListFrom stash position++-- | Handle one PatternItem anywhere in the text+lookupItemAnywhere :: Document -> PatternItem -> Stash -> Duckling [Node]+lookupItemAnywhere doc (Regex re) _ = lookupRegexAnywhere doc re+lookupItemAnywhere _doc (Predicate p) stash =+  return $ filter (p . token) $ Stash.toPosOrderedList stash++isPositionValid :: Int -> Document -> Node -> Bool+isPositionValid position sentence (Node {nodeRange = Range start _}) =+  Document.isAdjacent sentence position start++-- | A match is full if its rule pattern is empty.+-- (rule, endPosition, reversedRoute)+type Match = (Rule, Int, [Node])++-- | Recursively augments `matches`.+-- Discards partial matches stuck by a regex.+matchAll :: Document -> Stash -> [Match] -> Duckling [Match]+matchAll sentence stash matches = concatMapM mkNextMatches matches+  where+    mkNextMatches :: Match -> Duckling [Match]+    mkNextMatches match@(Rule {pattern = []}, _, _) = return [ match ]+    mkNextMatches match@(Rule {pattern = p:_}, _, _) = do+      nextMatches <- matchAll sentence stash =<< matchFirst sentence stash match+      return $ case p of+        Regex _ -> nextMatches+        Predicate _ -> match:nextMatches++-- | Returns all matches matching the first pattern item of `match`,+-- resuming from a Match position+matchFirst :: Document -> Stash -> Match -> Duckling [Match]+matchFirst _ _ (Rule {pattern = []}, _, _) = return []+matchFirst sentence stash (rule@(Rule {pattern = p:ps}), position, route) =+  map (mkMatch route newRule) <$> lookupItem sentence p stash position+  where+  newRule = rule { pattern = ps }++-- | Returns all matches matching the first pattern item of `match`,+-- starting anywhere+matchFirstAnywhere :: Document -> Stash -> Rule -> Duckling [Match]+matchFirstAnywhere _sentence _stash Rule {pattern = []} = return []+matchFirstAnywhere sentence stash rule@(Rule {pattern = p:ps}) =+  map (mkMatch [] newRule) <$> lookupItemAnywhere sentence p stash+  where+  newRule = rule { pattern = ps }++{-# INLINE mkMatch #-}+mkMatch :: [Node] -> Rule -> Node -> Match+mkMatch route newRule (node@Node {nodeRange = Range _ pos'}) =+  newRoute `seq` (newRule, pos', newRoute)+  where newRoute = node:route++-- | Finds new matches resulting from newly added tokens.+-- Produces new tokens from full matches.+parseString1+  :: [Rule] -> Document -> Stash -> Stash -> [Match]+  -> Duckling (Stash, [Match])+parseString1 rules sentence stash new matches = do+  -- Recursively match patterns.+  -- Find which `matches` can advance because of `new`.+  newPartial <- concatMapM (matchFirst sentence new) matches++  -- Find new matches resulting from newly added tokens (`new`)+  newMatches <- concatMapM (matchFirstAnywhere sentence new) rules++  (full, partial) <- L.partition (\(Rule {pattern}, _, _) -> null pattern)+    <$> matchAll sentence stash (newPartial ++ newMatches)++  -- Produce full matches as new tokens+  return ( Stash.fromList $ mapMaybe produce full+         , partial ++ matches+         )++-- | Produces all tokens recursively.+saturateParseString+  :: [Rule] -> Document -> Stash -> Stash -> [Match] -> Duckling Stash+saturateParseString rules sentence stash new matches = do+  (new', matches') <- parseString1 rules sentence stash new matches+  let stash' = Stash.union stash new'+  if Stash.null new'+    then return stash+    else saturateParseString rules sentence stash' new' matches'++parseString :: [Rule] -> Document -> Duckling Stash+parseString rules sentence = do+  (new, partialMatches) <-+    -- One the first pass we try all the rules+    parseString1 rules sentence Stash.empty Stash.empty []+  if Stash.null new+    then return Stash.empty+    else+    -- For subsequent passes, we only try rules starting with a predicate.+    saturateParseString headPredicateRules sentence new new partialMatches+  where+  headPredicateRules =+    [ rule | rule@(Rule {pattern = (Predicate _:_)}) <- rules ]++resolveNode :: Context -> Node -> Maybe ResolvedToken+resolveNode context n@Node{token = (Token _ dd), nodeRange = nodeRange} = do+  val <- resolve context dd+  Just Resolved+    { range = nodeRange+    , node = n+    , jsonValue = toJSON val+    }
+ Duckling/Engine/Regex.hs view
@@ -0,0 +1,14 @@+-- 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.Engine.Regex+  ( matchAll+  , matchOnce+  ) where++import Text.Regex.Base (matchAll, matchOnce)
+ Duckling/Lang.hs view
@@ -0,0 +1,54 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Lang+  ( Lang(..)+  ) where++import Prelude++import Data.Hashable+import GHC.Generics+import TextShow (TextShow)+import qualified TextShow as TS++data Lang+  = AR+  | DA+  | DE+  | EN+  | ES+  | ET+  | FR+  | GA+  | HE+  | HR+  | ID+  | IT+  | JA+  | KO+  | MY+  | NB+  | NL+  | PL+  | PT+  | RO+  | RU+  | SV+  | TR+  | UK+  | VI+  | ZH+  deriving (Bounded, Enum, Eq, Generic, Hashable, Ord, Read, Show)++instance TextShow Lang where+  showb = TS.fromString . show
+ Duckling/Numeral/AR/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.AR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = AR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "صفر"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "واحد"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "أربعة"+             , "أربع"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "ستة"+             , "ست"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "ثلاث و ثلاثون"+             ]+  , 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 525)+             [ "خمسمائة و خمسة و عشرون"+             , "525"+             ]+  , examples (NumeralValue 21)+             [ "واحدة و عشرون"+             , "21"+             ]+  , examples (NumeralValue 24)+             [ "أربعة و عشرون"+             , "24"+             ]+  , examples (NumeralValue 26)+             [ "ستة و عشرون"+             , "26"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 فاصلة 1"+             , "واحد فاصلة واحد"+             ]+  , examples (NumeralValue 0.77)+             [ "0.77"+             , ".77"+             ]+  , examples (NumeralValue 100000)+             [ "100000"+             , "100 الف"+             ]+  , examples (NumeralValue 10000)+             [ "10000"+             , "10 آلاف"+             ]+  , examples (NumeralValue 3000000)+             [ "3 ملايين"+             , "3000000"+             ]+  , examples (NumeralValue (-1200000))+             [ "-1200000"+             ]+  ]
+ Duckling/Numeral/AR/Rules.hs view
@@ -0,0 +1,371 @@+-- 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 #-}++module Duckling.Numeral.AR.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer 4"+  , pattern =+    [ regex "(\x0623\x0631\x0628\x0639(\x0629)?)"+    ]+  , prod = \_ -> integer 4+  }++ruleInteger23 :: Rule+ruleInteger23 = Rule+  { name = "integer 101..999"+  , pattern =+    [ oneOf [100, 200 .. 900]+    , regex "\x0648"+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger18 :: Rule+ruleInteger18 = Rule+  { name = "integer 12"+  , pattern =+    [ regex "(\x0625\x062b\x0646(\x062a)?\x0649 \x0639\x0634\x0631)"+    ]+  , prod = \_ -> integer 12+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleInteger19 :: Rule+ruleInteger19 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(\x0639\x0634\x0631\x0648\x0646|\x062b\x0644\x0627\x062b\x0648\x0646|\x0623\x0631\x0628\x0639\x0648\x0646|\x062e\x0645\x0633\x0648\x0646|\x0633\x062a\x0648\x0646|\x0633\x0628\x0639\x0648\x0646|\x062b\x0645\x0627\x0646\x0648\x0646|\x062a\x0633\x0639\x0648\x0646)"+    ]+  , prod = \tokens -> case tokens of+      Token RegexMatch (GroupMatch (match:_)):_ -> case match of+        "\x0639\x0634\x0631\x0648\x0646" -> integer 20+        "\x062b\x0644\x0627\x062b\x0648\x0646" -> integer 30+        "\x0623\x0631\x0628\x0639\x0648\x0646" -> integer 40+        "\x062e\x0645\x0633\x0648\x0646" -> integer 50+        "\x0633\x062a\x0648\x0646" -> integer 60+        "\x0633\x0628\x0639\x0648\x0646" -> integer 70+        "\x062b\x0645\x0627\x0646\x0648\x0646" -> integer 80+        "\x062a\x0633\x0639\x0648\x0646" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger22 :: Rule+ruleInteger22 = Rule+  { name = "integer 21..99"+  , pattern =+    [ numberBetween 1 10+    , regex "\x0648"+    , oneOf [20, 30 .. 90]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger21 :: Rule+ruleInteger21 = Rule+  { name = "integer (13..19)"+  , pattern =+    [ numberBetween 3 10+    , numberWith TNumeral.value (== 10)+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 10+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleInteger15 :: Rule+ruleInteger15 = Rule+  { name = "integer 11"+  , pattern =+    [ regex "(\x0625\x062d\x062f\x0649 \x0639\x0634\x0631(\x0629)?)"+    ]+  , prod = \_ -> integer 11+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\.\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDecimal True match+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(\x0645\x0627\x0626\x0629|\x0645\x0626\x0627\x062a|\x0623\x0644\x0641|\x0627\x0644\x0641|\x0622\x0644\x0627\x0641|\x0645\x0644\x0627\x064a\x064a(\x0646)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "\x0645\x0627\x0626\x0629" ->+          double 1e2 >>= withGrain 2 >>= withMultipliable+        "\x0645\x0626\x0627\x062a" ->+          double 1e2 >>= withGrain 2 >>= withMultipliable+        "\x0623\x0644\x0641" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "\x0627\x0644\x0641" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "\x0622\x0644\x0627\x0641" ->+          double 1e3 >>= withGrain 3 >>= withMultipliable+        "\x0645\x0644\x0627\x064a\x064a" ->+          double 1e6 >>= withGrain 6 >>= withMultipliable+        "\x0645\x0644\x0627\x064a\x064a\x0646" ->+          double 1e6 >>= withGrain 6 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 2"+  , pattern =+    [ regex "(\x0627\x062b\x0646\x0627\x0646|\x0627\x062b\x0646\x064a\x0646)"+    ]+  , prod = \_ -> integer 2+  }++ruleInteger13 :: Rule+ruleInteger13 = Rule+  { name = "integer 9"+  , pattern =+    [ regex "(\x062a\x0633\x0639\x0629|\x062a\x0633\x0639)"+    ]+  , prod = \_ -> integer 9+  }++ruleInteger12 :: Rule+ruleInteger12 = Rule+  { name = "integer 8"+  , pattern =+    [ regex "(\x062b\x0645\x0627\x0646\x064a\x0629|\x062b\x0645\x0627\x0646)"+    ]+  , prod = \_ -> integer 8+  }++ruleNumeralsPrefixWithMinus :: Rule+ruleNumeralsPrefixWithMinus = Rule+  { name = "numbers prefix with -, minus"+  , pattern =+    [ regex "-"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double (v * (- 1))+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer 5"+  , pattern =+    [ regex "(\x062e\x0645\x0633)(\x0629)?"+    ]+  , prod = \_ -> integer 5+  }++ruleInteger14 :: Rule+ruleInteger14 = Rule+  { name = "integer 10"+  , pattern =+    [ regex "(\x0639\x0634\x0631\x0629|\x0639\x0634\x0631)"+    ]+  , prod = \_ -> integer 10+  }++ruleInteger9 :: Rule+ruleInteger9 = Rule+  { name = "integer 6"+  , pattern =+    [ regex "(\x0633\x062a(\x0629)?)"+    ]+  , prod = \_ -> integer 6+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "(\x0635\x0641\x0631)"+    ]+  , prod = \_ -> integer 0+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 3"+  , pattern =+    [ regex "(\x062b\x0644\x0627\x062b|\x062b\x0644\x0627\x062b\x0629)"+    ]+  , prod = \_ -> integer 3+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 1"+  , pattern =+    [ regex "(\x0648\x0627\x062d\x062f\x0629|\x0648\x0627\x062d\x062f\x0647|\x0648\x0627\x062d\x062f)"+    ]+  , prod = \_ -> integer 1+  }++ruleInteger11 :: Rule+ruleInteger11 = Rule+  { name = "integer 7"+  , pattern =+    [ regex "(\x0633\x0628\x0639\x0629|\x0633\x0628\x0639)"+    ]+  , prod = \_ -> integer 7+  }++ruleInteger20 :: Rule+ruleInteger20 = Rule+  { name = "integer (100..900)"+  , pattern =+    [ regex "(\x0645\x0627\x0626\x0629|\x0645\x0627\x0626\x062a\x0627\x0646|\x062b\x0644\x0627\x062b\x0645\x0627\x0626\x0629|\x0623\x0631\x0628\x0639\x0645\x0627\x0626\x0629|\x062e\x0645\x0633\x0645\x0627\x0626\x0629|\x0633\x062a\x0645\x0627\x0626\x0629|\x0633\x0628\x0639\x0645\x0627\x0626\x0629|\x062b\x0645\x0627\x0646\x0645\x0627\x0626\x0629|\x062a\x0633\x0639\x0645\x0627\x0626\x0629)"+    ]+  , prod = \tokens -> case tokens of+      Token RegexMatch (GroupMatch (match:_)):_ -> case match of+        "\x0645\x0627\x0626\x0629" -> integer 100+        "\x0633\x0628\x0639\x0645\x0627\x0626\x0629" -> integer 700+        "\x062e\x0645\x0633\x0645\x0627\x0626\x0629" -> integer 500+        "\x0623\x0631\x0628\x0639\x0645\x0627\x0626\x0629" -> integer 400+        "\x0633\x062a\x0645\x0627\x0626\x0629" -> integer 600+        "\x0645\x0627\x0626\x062a\x0627\x0646" -> integer 200+        "\x062b\x0644\x0627\x062b\x0645\x0627\x0626\x0629" -> integer 300+        "\x062b\x0645\x0627\x0646\x0645\x0627\x0626\x0629" -> integer 800+        "\x062a\x0633\x0639\x0645\x0627\x0626\x0629" -> integer 900+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "\x0641\x0627\x0635\x0644\x0629"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ,"+  , pattern =+    [ regex "(\\d{1,3}(,\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger11+  , ruleInteger12+  , ruleInteger13+  , ruleInteger14+  , ruleInteger15+  , ruleInteger18+  , ruleInteger19+  , ruleInteger2+  , ruleInteger20+  , ruleInteger21+  , ruleInteger22+  , ruleInteger23+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger7+  , ruleInteger9+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithMinus+  , rulePowersOfTen+  ]
+ Duckling/Numeral/DA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.DA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = DA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nul"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "én"+             , "en"+             , "ét"+             , "et"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "to"+             , "et par"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "fjorten"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "seksten"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "sytten"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "Atten"+             ]+  , 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"+             , "minus 1.200.000"+             , "negativ 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tusind"+             , "fem tusinde"+             , "fem Tusind"+             ]+  ]
+ Duckling/Numeral/DA/Rules.hs view
@@ -0,0 +1,327 @@+-- 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 #-}++module Duckling.Numeral.DA.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus\\s?|negativ\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ v * (-1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "(nogle )?f\x00e5"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "ti"+    ]+  , 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton '.') 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , 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+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "enkelt"+    ]+  , prod = \_ -> integer 1 >>= withGrain 1+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , dimension Numeral+    ]+  , 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\\$\x20ac]|$)"+    ]+  , 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+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(hundrede?|tusinde?|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+        "tusind"    -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tusinde"   -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "millioner" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++ruleAPair :: Rule+ruleAPair = Rule+  { name = "a pair"+  , pattern =+    [ regex "et par"+    ]+  , prod = \_ -> integer 2 >>= withGrain 1+  }++ruleNumeralsOg :: Rule+ruleNumeralsOg = Rule+  { name = "numbers og"+  , pattern =+    [ numberBetween 1 10+    , regex "og"+    , oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "dusin"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ("ingen", 0)+  , ("nul", 0)+  , ("intet", 0)+  , ("en", 1)+  , ("et", 1)+  , ("\x00e9n", 1)+  , ("\x00e9t", 1)+  , ("to", 2)+  , ("tre", 3)+  , ("fire", 4)+  , ("fem", 5)+  , ("seks", 6)+  , ("syv", 7)+  , ("otte", 8)+  , ("ni", 9)+  , ("ti", 10)+  , ("elleve", 11)+  , ("tolv", 12)+  , ("tretten", 13)+  , ("fjorten", 14)+  , ("femten", 15)+  , ("seksten", 16)+  , ("sytten", 17)+  , ("atten", 18)+  , ("nitten", 19)+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(intet|ingen|nul|en|et|\x00e9n|\x00e9t|to|tretten|tre|fire|femten|fem|seksten|seks|syv|otte|nitten|ni|ti|elleve|tolv|fjorten|sytten|atten)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroNineteenMap >>= integer+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(tyve|tredive|fyrre|halvtreds|tres|halvfjerds|firs|halvfems)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "tyve" -> integer 20+        "tredive" -> integer 30+        "fyrre" -> integer 40+        "halvtreds" -> integer 50+        "tres" -> integer 60+        "halvfjerds" -> integer 70+        "firs" -> integer 80+        "halvfems" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "komma"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAPair+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsOg+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSingle+  , ruleTen+  ]
+ Duckling/Numeral/DE/Corpus.hs view
@@ -0,0 +1,133 @@+-- 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.DE.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = DE}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "null"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "eins"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "Drei"+             ]+  , examples (NumeralValue 30)+             [ "30"+             , "dreissig"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "drei Und dreissig"+             , "dreiunddreissig"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "vierzehn"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "sechzehn"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "Siebzehn"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "achtzehn"+             ]+  , examples (NumeralValue 200)+             [ "200"+             , "zwei hundert"+             ]+  , examples (NumeralValue 102)+             [ "102"+             , "Hundert zwei"+             ]+  , examples (NumeralValue 1.1)+             [ "1,1"+             , "1 komma 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"+             , "minus 1.200.000"+             , "negativ 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tausend"+             , "fünf tausend"+             ]+  , examples (NumeralValue 200000)+             [ "zwei hundert tausend"+             ]+  , examples (NumeralValue 721012)+             [ "sieben hundert einundzwanzig tausend zwölf"+             ]+  , examples (NumeralValue 31256721)+             [ "ein und dreissig millionen zwei hundert sechs und fünfzig tausend sieben hundert ein und zwanzig"+             ]+  , examples (NumeralValue 1416.15)+             [ "1416,15"+             ]+  , examples (NumeralValue 1416.15)+             [ "1.416,15"+             ]+  , examples (NumeralValue 1000000.0)+             [ "1.000.000,00"+             ]+  ]
+ Duckling/Numeral/DE/Rules.hs view
@@ -0,0 +1,389 @@+-- 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 #-}++module Duckling.Numeral.DE.Rules+  ( rules ) where++import Control.Monad (join)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus|negativ"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ v * (- 1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "mehrere"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "zehn"+    ]+  , 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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer ([2-9][1-9])"+  , pattern =+    [ regex "(ein|zwei|drei|vier|f\x00fcnf|sechs|sieben|acht|neun)und(zwanzig|dreissig|vierzig|f\x00fcnfzig|sechzig|siebzig|achtzig|neunzig)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- case Text.toLower m1 of+          "ein" -> Just 1+          "zwei" -> Just 2+          "drei" -> Just 3+          "vier" -> Just 4+          "f\x00fcnf" -> Just 5+          "sechs" -> Just 6+          "sieben" -> Just 7+          "acht" -> Just 8+          "neun" -> Just 9+          _ -> Nothing+        v2 <- case Text.toLower m2 of+          "zwanzig" -> Just 20+          "dreissig" -> Just 30+          "vierzig" -> Just 40+          "f\x00fcnfzig" -> Just 50+          "sechzig" -> Just 60+          "siebzig" -> Just 70+          "achtzig" -> Just 80+          "neunzig" -> Just 90+          _ -> Nothing+        integer $ v1 + v2+      _ -> Nothing+  }++ruleNumeralsUnd :: Rule+ruleNumeralsUnd = Rule+  { name = "numbers und"+  , pattern =+    [ numberBetween 1 10+    , regex "und"+    , oneOf [20, 30 .. 90]+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , dimension Numeral+    ]+  , 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\\$\x20ac]|$)"+    ]+  , 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 "(ein )?paar"+    ]+  , prod = \_ -> integer 2+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "dutzend"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(hunderte?|tausende?|million(en)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "hundert"   -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "hunderte"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tausend"   -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tausende"  -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "millionen" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ("keine", 0)+  , ("null", 0)+  , ("nichts", 0)+  , ("keiner", 0)+  , ("kein", 0)+  , ("keins", 0)+  , ("keinen", 0)+  , ("keines", 0)+  , ("einer", 1)+  , ("eins", 1)+  , ("ein", 1)+  , ("eine", 1)+  , ("einser", 1)+  , ("zwei", 2)+  , ("drei", 3)+  , ("vier", 4)+  , ("f\x00fcnf", 5)+  , ("sechs", 6)+  , ("sieben", 7)+  , ("acht", 8)+  , ("neun", 9)+  , ("zehn", 10)+  , ("elf", 11)+  , ("zw\x00f6lf", 12)+  , ("dreizehn", 13)+  , ("vierzehn", 14)+  , ("f\x00fcnfzehn", 15)+  , ("sechzehn", 16)+  , ("siebzehn", 17)+  , ("achtzehn", 18)+  , ("neunzehn", 19)+  ]++ruleToNineteen :: Rule+ruleToNineteen = Rule+  { name = "integer (0..19)"+  -- e.g. fourteen must be before four,+  -- otherwise four will always shadow fourteen+  , pattern = [regex "(keine?|keine?s|keiner|keinen|null|nichts|eins?(er)?|zwei|dreizehn|drei|vierzehn|vier|f\x00fcnf|sechzehn|sechs|siebzehn|sieben|achtzehn|acht|neunzehn|neun|elf|zw\x00f6lf|f\x00fcfzehn)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroNineteenMap >>= integer+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(keine?|keine?s|keiner|keinen|null|nichts|eins?(er)?|zwei|dreizehn|drei|vierzehn|vier|f\x00fcnf|sechzehn|sechs|siebzehn|sieben|achtzehn|acht|neunzehn|neun|elf|zw\x00f6lf|f\x00fcfzehn)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "nichts" -> integer 0+        "keine" -> integer 0+        "null" -> integer 0+        "keiner" -> integer 0+        "kein" -> integer 0+        "keins" -> integer 0+        "keinen" -> integer 0+        "keines" -> integer 0+        "einer" -> integer 1+        "eins" -> integer 1+        "ein" -> integer 1+        "eine" -> integer 1+        "zwei" -> integer 2+        "drei" -> integer 3+        "vier" -> integer 4+        "f\x00fcnf" -> integer 5+        "sechs" -> integer 6+        "sieben" -> integer 7+        "acht" -> integer 8+        "neun" -> integer 9+        "zehn" -> integer 10+        "elf" -> integer 11+        "zw\x00f6lf" -> integer 12+        "dreizehn" -> integer 13+        "vierzehn" -> integer 14+        "f\x00fcnfzehn" -> integer 15+        "sechzehn" -> integer 16+        "siebzehn" -> integer 17+        "achtzehn" -> integer 18+        "neunzehn" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(zwanzig|dreissig|vierzig|f\x00fcnfzig|sechzig|siebzig|achtzig|neunzig)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "zwanzig" -> integer 20+        "dreissig" -> integer 30+        "vierzig" -> integer 40+        "f\x00fcnfzig" -> integer 50+        "sechzig" -> integer 60+        "siebzig" -> integer 70+        "achtzig" -> integer 80+        "neunzig" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "komma"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , ruleNumeralsUnd+  , rulePowersOfTen+  , ruleTen+  , ruleToNineteen+  ]
+ Duckling/Numeral/EN/Corpus.hs view
@@ -0,0 +1,157 @@+-- 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.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Numeral.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "naught"+             , "nought"+             , "zero"+             , "nil"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "one"+             , "single"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "two"+             , "a pair"+             , "a couple"+             , "a couple of"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "three"+             , "a few"+             , "few"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "ten"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "twelve"+             , "a dozen"+             , "a dozen of"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "fourteen"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "sixteen"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "seventeen"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "eighteen"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "thirty three"+             , "0033"+             ]+  , examples (NumeralValue 24)+             [ "24"+             , "2 dozens"+             , "two dozen"+             , "Two dozen"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 point 1"+             ]+  , examples (NumeralValue 0.77)+             [ ".77"+             , "0.77"+             , "point 77"+             ]+  , examples (NumeralValue 100000)+             [ "100,000"+             , "100,000.0"+             , "100000"+             , "100K"+             , "100k"+             , "one hundred thousand"+             ]+  , examples (NumeralValue 3e6)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3,000,000"+             , "3 million"+             ]+  , examples (NumeralValue 1.2e6)+             [ "1,200,000"+             , "1200000"+             , "1.2M"+             , "1200k"+             , ".0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 thousand"+             , "five thousand"+             ]+  , examples (NumeralValue (-1.2e6))+             [ "- 1,200,000"+             , "-1200000"+             , "minus 1,200,000"+             , "negative 1200000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  , examples (NumeralValue 122)+             [ "one twenty two"+             , "ONE TwentY tWO"+             ]+  , examples (NumeralValue 2e5)+             [ "two Hundred thousand"+             ]+  , examples (NumeralValue 21011)+             [ "twenty-one thousand Eleven"+             ]+  , examples (NumeralValue 721012)+             [ "seven hundred twenty-one thousand twelve"+             , "seven hundred twenty-one thousand and twelve"+             ]+  , examples (NumeralValue 31256721)+             [ "thirty-one million two hundred fifty-six thousand seven hundred twenty-one"+             ]+  , examples (NumeralValue 2400)+             [ "two hundred dozens"+             , "200 dozens"+             ]+  , examples (NumeralValue 2200000)+             [ "two point two million"+             ]+  ]
+ Duckling/Numeral/EN/Rules.hs view
@@ -0,0 +1,303 @@+-- 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 #-}++module Duckling.Numeral.EN.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleIntegers :: Rule+ruleIntegers = Rule+  { name = "integer (numeric)"+  , pattern = [regex "(\\d{1,18})"]+  , prod = \tokens ->+      case tokens of+        (Token RegexMatch (GroupMatch (match:_)):_) -> do+          v <- parseInt match+          integer $ toInteger v+        _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "a dozen of"+  , pattern =+    [ regex "(a )?dozens?( of)?"+    ]+  , prod = \_ -> integer 12 >>= withMultipliable+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ( "naught", 0 )+  , ( "nil"   , 0 )+  , ( "nought", 0 )+  , ( "none"  , 0 )+  , ( "zero"  , 0 )+  , ( "zilch" , 0 )+  , ( "one"   , 1 )+  , ( "single", 1 )+  , ( "two", 2 )+  , ( "a couple", 2 )+  , ( "a couple of", 2 )+  , ( "couple", 2 )+  , ( "couples", 2 )+  , ( "couple of", 2 )+  , ( "couples of", 2 )+  , ( "a pair", 2 )+  , ( "a pair of", 2 )+  , ( "pair", 2 )+  , ( "pairs", 2 )+  , ( "pair of", 2 )+  , ( "pairs of", 2 )+  , ( "three", 3 )+  , ( "a few", 3 )+  , ( "few", 3 )+  , ( "four", 4 )+  , ( "five", 5 )+  , ( "six", 6 )+  , ( "seven", 7 )+  , ( "eight", 8 )+  , ( "nine", 9 )+  , ( "ten", 10 )+  , ( "eleven", 11 )+  , ( "twelve", 12 )+  , ( "thirteen", 13 )+  , ( "fourteen", 14 )+  , ( "fifteen", 15 )+  , ( "sixteen", 16 )+  , ( "seventeen", 17 )+  , ( "eighteen", 18 )+  , ( "nineteen", 19 )+  ]++ruleToNineteen :: Rule+ruleToNineteen = Rule+  { name = "integer (0..19)"+  -- e.g. fourteen must be before four, otherwise four will always shadow fourteen+  , pattern = [regex "(none|zilch|naught|nought|nil|zero|one|single|two|(a )?(pair|couple)s?( of)?|three|(a )?few|fourteen|four|fifteen|five|sixteen|six|seventeen|seven|eighteen|eight|nineteen|nine|ten|eleven|twelve|thirteen)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroNineteenMap >>= integer+      _ -> Nothing+  }++ruleTens :: Rule+ruleTens = Rule+  { name = "integer (20..90)"+  , pattern = [regex "(twenty|thirty|fou?rty|fifty|sixty|seventy|eighty|ninety)"]+  , prod = \tokens ->+      case tokens of+        (Token RegexMatch (GroupMatch (match : _)) : _) ->+          case Text.toLower match of+            "twenty"  -> integer 20+            "thirty"  -> integer 30+            "forty"   -> integer 40+            "fourty"  -> integer 40+            "fifty"   -> integer 50+            "sixty"   -> integer 60+            "seventy" -> integer 70+            "eighty"  -> integer 80+            "ninety"  -> integer 90+            _         -> Nothing+        _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(hundred|thousand|million|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+      _ -> Nothing+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..99"+  , pattern = [oneOf [20,30..90], numberBetween 1 10]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData { TNumeral.value = tens }) :+       Token Numeral (NumeralData { TNumeral.value = units }) :+       _) -> double (tens + units)+      _ -> Nothing+  }++ruleSkipHundreds :: Rule+ruleSkipHundreds = Rule+  { name = "one twenty two"+  , pattern = [numberBetween 1 10, numberBetween 10 100]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData { TNumeral.value = hundreds }) :+       Token Numeral (NumeralData { TNumeral.value = rest }) :+       _) -> double (hundreds*100 + rest)+      _ -> Nothing+  }++ruleDotSpelledOut :: Rule+ruleDotSpelledOut = Rule+  { name = "one point 2"+  , pattern =+    [ dimension Numeral+    , regex "point|dot"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleLeadingDotSpelledOut :: Rule+ruleLeadingDotSpelledOut = Rule+  { name = "point 77"+  , pattern =+    [ regex "point|dot"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double . decimalsToDouble $ TNumeral.value nd+      _ -> Nothing+  }++ruleDecimals :: Rule+ruleDecimals = Rule+  { name = "decimal number"+  , pattern = [regex "(\\d*\\.\\d+)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal True match+      _ -> Nothing+  }++ruleCommas :: Rule+ruleCommas = Rule+  { name = "comma-separated numbers"+  , pattern = [regex "(\\d+(,\\d\\d\\d)+(\\.\\d+)?)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleSuffixes :: Rule+ruleSuffixes = Rule+  { name = "suffixes (K,M,G))"+  , pattern =+    [ dimension Numeral+    , regex "(k|m|g)(?=[\\W$\x20ac\x00a2\x00a3]|$)"+    ]+  , prod = \tokens ->+      case tokens of+        (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 "-|minus\\s?|negative\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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 =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "and"+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntegers+  , ruleToNineteen+  , ruleTens+  , rulePowersOfTen+  , ruleCompositeTens+  , ruleSkipHundreds+  , ruleDotSpelledOut+  , ruleLeadingDotSpelledOut+  , ruleDecimals+  , ruleCommas+  , ruleSuffixes+  , ruleNegative+  , ruleSum+  , ruleSumAnd+  , ruleMultiply+  , ruleDozen+  ]
+ Duckling/Numeral/ES/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.ES.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ES}, 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"+             ]+  ]
+ Duckling/Numeral/ES/Rules.hs view
@@ -0,0 +1,315 @@+-- 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 #-}++module Duckling.Numeral.ES.Rules+  ( rules ) where++import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|menos"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ v * (- 1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> 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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot 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+  }++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 )+  ]++ruleNumeral2 :: Rule+ruleNumeral2 = Rule+  { name = "number (20..90)"+  , pattern =+    [ regex "(veinte|treinta|cuarenta|cincuenta|sesenta|setenta|ochenta|noventa)"+    ]+  , prod = \tokens -> case tokens of+      (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\x00e9s" , 3 )+  , ( "tres" , 3 )+  , ( "cuatro" , 4 )+  , ( "cinco" , 5 )+  , ( "seis" , 6 )+  , ( "s\x00e9is" , 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(\x00e9|e)s|cuatro|cinco|s(e|\x00e9)is|siete|ocho|nueve|die(z|s)|once|doce|trece|catorce|quince)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToFifteenMap >>= integer+      _ -> Nothing+  }++sixteenToTwentyNineMap :: HashMap.HashMap Text.Text Integer+sixteenToTwentyNineMap = HashMap.fromList+  [ ( "dieciseis" , 16 )+  , ( "diesis\x00e9is" , 16 )+  , ( "diesiseis" , 16 )+  , ( "diecis\x00e9is" , 16 )+  , ( "diecisiete" , 17 )+  , ( "dieciocho" , 18 )+  , ( "diecinueve" , 19 )+  , ( "veintiuno" , 21 )+  , ( "veintiuna" , 21 )+  , ( "veintidos" , 22 )+  , ( "veintitr\x00e9s" , 23 )+  , ( "veintitres" , 23 )+  , ( "veinticuatro" , 24 )+  , ( "veinticinco" , 25 )+  , ( "veintis\x00e9is" , 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(\x00e9|e)is|diecisiete|dieciocho|diecinueve|veintiun(o|a)|veintidos|veintitr(\x00e9|e)s|veinticuatro|veinticinco|veintis(\x00e9|e)is|veintisiete|veintiocho|veintinueve)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) sixteenToTwentyNineMap >>= integer+      _ -> Nothing+  }++ruleNumeral3 :: Rule+ruleNumeral3 = Rule+  { name = "number (16..19)"+  , pattern =+    [ numberWith TNumeral.value (== 10)+    , regex "y"+    , numberBetween 6 10+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ 10 + v+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++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 )+  ]+++ruleNumeral6 :: Rule+ruleNumeral6 = Rule+  { name = "number 100..1000 "+  , pattern =+    [ regex "(cien(to)?s?|doscientos|trescientos|cuatrocientos|quinientos|seiscientos|setecientos|ochocientos|novecientos|mil)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) oneHundredToThousandMap >>= integer+      _ -> Nothing+  }++ruleNumeral4 :: Rule+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+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 200..999"+  , pattern =+    [ 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+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "punto"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeral2+  , ruleNumeral3+  , ruleNumeral4+  , ruleNumeral5+  , ruleNumeral6+  , ruleNumeralDotNumeral+  , ruleNumerals+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/ET/Corpus.hs view
@@ -0,0 +1,109 @@+-- 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.ET.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ET}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "null"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "üks"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "Kolmkümmend kolm"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "neliteist"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "kuusteist"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "Seitseteist"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "kaheksateist"+             ]+  , 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"+             , "100 000"+             ]+  , examples (NumeralValue 3000000)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3,000,000"+             , "3 000 000"+             ]+  , examples (NumeralValue 1200000)+             [ "1,200,000"+             , "1200000"+             , "1.2M"+             , "1200K"+             , ".0012G"+             , "1 200 000"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1,200,000"+             , "-1200000"+             , "miinus 1,200,000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  , examples (NumeralValue 5000)+             [ "viis tuhat"+             ]+  , examples (NumeralValue 200000)+             [ "kakssada tuhat"+             ]+  , examples (NumeralValue 21011)+             [ "kakskümmend üks Tuhat üksteist"+             ]+  , examples (NumeralValue 721012)+             [ "seitsesada kakskümmend üks tuhat kaksteist"+             ]+  , examples (NumeralValue 31256721)+             [ "kolmkümmend üks miljonit kakssada viiskümmend kuus tuhat seitsesada kakskümmend üks"+             ]+  ]
+ Duckling/Numeral/ET/Rules.hs view
@@ -0,0 +1,306 @@+-- 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 #-}++module Duckling.Numeral.ET.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleIntegerWithThousandsSeparatorSpace :: Rule+ruleIntegerWithThousandsSeparatorSpace = Rule+  { name = "integer with thousands separator space"+  , pattern =+    [ regex "(\\d{1,3}(\\s\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ' ') Text.empty match) >>= double+      _ -> Nothing+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|miinus|negatiivne"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ v * (-1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         v <- parseInt match+         integer $ toInteger v+      _ -> Nothing+  }++ruleACoupleOf :: Rule+ruleACoupleOf = Rule+  { name = "a couple of"+  , pattern =+    [ regex "paar"+    ]+  , prod = \_ -> integer 2+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "k\x00fcmme"+    ]+  , 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):_) -> double $ v1 + v2+      _ -> Nothing+  }++ruleAFew :: Rule+ruleAFew = Rule+  { name = "(a )?few"+  , pattern =+    [ regex "m\x00f5ni"+    ]+  , prod = \_ -> integer 3+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern = [regex "(sada|tuhat|miljoni?t?)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "sada"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tuhat" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        _       -> double 1e6 >>= withGrain 6 >>= withMultipliable+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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\\$\x20ac]|$)"+    ]+  , 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+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(null|\x00fcksteist|\x00fcks|kaksteist|kaks|kolmteist|kolm|neliteist|neli|viisteist|viis|kuusteist|kuus|seitseteist|seitse|kaheksateist|kaheksa|\x00fcheksateist|\x00fcheksa|k\x00fcmme)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "null" -> integer 0+        "\x00fcks" -> integer 1+        "kaks" -> integer 2+        "kolm" -> integer 3+        "neli" -> integer 4+        "viis" -> integer 5+        "kuus" -> integer 6+        "seitse" -> integer 7+        "kaheksa" -> integer 8+        "\x00fcheksa" -> integer 9+        "k\x00fcmme" -> integer 10+        "\x00fcksteist" -> integer 11+        "kaksteist" -> integer 12+        "kolmteist" -> integer 13+        "neliteist" -> integer 14+        "viisteist" -> integer 15+        "kuusteist" -> integer 16+        "seitseteist" -> integer 17+        "kaheksateist" -> integer 18+        "\x00fcheksateist" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer (200..900)"+  , pattern =+    [ regex "(kakssada|kolmsada|nelisada|viissada|kuussada|seitsesada|kaheksasada|\x00fcheksasada)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "kakssada"        -> integer 200 >>= withGrain 2 >>= withMultipliable+        "kolmsada"        -> integer 300 >>= withGrain 2 >>= withMultipliable+        "nelisada"        -> integer 400 >>= withGrain 2 >>= withMultipliable+        "viissada"        -> integer 500 >>= withGrain 2 >>= withMultipliable+        "kuussada"        -> integer 600 >>= withGrain 2 >>= withMultipliable+        "seitsesada"      -> integer 700 >>= withGrain 2 >>= withMultipliable+        "kaheksasada"     -> integer 800 >>= withGrain 2 >>= withMultipliable+        "\x00fcheksasada" -> integer 900 >>= withGrain 2 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "((kaks|kolm|neli|viis|kuus|seitse|kaheksa|(\x00fc)heksa)k(\x00fc)mmend)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "kaksk\x00fcmmend" -> integer 20+        "kolmk\x00fcmmend" -> integer 30+        "nelik\x00fcmmend" -> integer 40+        "viisk\x00fcmmend" -> integer 50+        "kuusk\x00fcmmend" -> integer 60+        "seitsek\x00fcmmend" -> integer 70+        "kaheksak\x00fcmmend" -> integer 80+        "\x00fcheksak\x00fcmmend" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "dot|point"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ,"+  , pattern =+    [ regex "(\\d{1,3}(,\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleACoupleOf+  , ruleAFew+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntegerWithThousandsSeparatorSpace+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleTen+  ]
+ Duckling/Numeral/FR/Corpus.hs view
@@ -0,0 +1,127 @@+-- 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.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "zero"+             , "zéro"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "un"+             , "une"+             ]+  , examples (NumeralValue 11)+             [ "onze"+             ]+  , examples (NumeralValue 17)+             [ "dix sept"+             , "dix-sept"+             ]+  , examples (NumeralValue 21)+             [ "vingt et un"+             , "vingt-et-un"+             ]+  , examples (NumeralValue 23)+             [ "vingt trois"+             , "vingt-trois"+             ]+  , examples (NumeralValue 70)+             [ "soixante dix"+             ]+  , examples (NumeralValue 71)+             [ "soixante onze"+             ]+  , examples (NumeralValue 78)+             [ "soixante dix huit"+             ]+  , examples (NumeralValue 73)+             [ "soixante treize"+             ]+  , examples (NumeralValue 80)+             [ "quatre vingt"+             ]+  , examples (NumeralValue 81)+             [ "quatre vingt un"+             ]+  , examples (NumeralValue 82)+             [ "quatre vingt deux"+             ]+  , examples (NumeralValue 90)+             [ "quatre vingt dix"+             ]+  , examples (NumeralValue 91)+             [ "quatre vingt onze"+             ]+  , examples (NumeralValue 92)+             [ "quatre vingt douze"+             ]+  , examples (NumeralValue 99)+             [ "quatre vingt dix neuf"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "trente trois"+             , "trente-trois"+             , "trente 3"+             ]+  , examples (NumeralValue 118)+             [ "cent dix-huit"+             ]+  , examples (NumeralValue 4020)+             [ "quatre mille vingt"+             ]+  , examples (NumeralValue 100000)+             [ "100.000"+             , "100000"+             , "100K"+             , "100k"+             , "cent mille"+             ]+  , examples (NumeralValue 3000000)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3.000.000"+             , "trois millions"+             ]+  , examples (NumeralValue 1200000)+             [ "1.200.000"+             , "1200000"+             , "1,2M"+             , "1200K"+             , ",0012G"+             , "un million deux cent mille"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1.200.000"+             , "-1200000"+             , "moins 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  ]
+ Duckling/Numeral/FR/Rules.hs view
@@ -0,0 +1,330 @@+-- 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 #-}++module Duckling.Numeral.FR.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.Maybe+import Data.String++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++ruleNumerals4 :: Rule+ruleNumerals4 = Rule+  { name = "numbers 81"+  , pattern =+    [ numberWith TNumeral.value (== 80)+    , numberWith TNumeral.value (== 1)+    ]+  , prod = \_ -> integer 81+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|moins"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ v * (-1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         v <- parseInt match+         integer $ toInteger v+      _ -> Nothing+  }++ruleNumerals2 :: Rule+ruleNumerals2 = Rule+  { name = "numbers 22..29 32..39 .. 52..59"+  , pattern =+    [ oneOf [20, 50, 40, 30]+    , numberBetween 2 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> 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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleNumeral2Map :: HashMap Text Integer+ruleNumeral2Map = HashMap.fromList+  [ ( "vingt"    , 20 )+  , ( "trente"   , 30 )+  , ( "quarante" , 40 )+  , ( "cinquante", 50 )+  , ( "soixante" , 60 )+  ]++ruleNumeral2 :: Rule+ruleNumeral2 = Rule+  { name = "number (20..60)"+  , pattern =+    [ regex "(vingt|trente|quarante|cinquante|soixante)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) ruleNumeral2Map >>= integer+      _ -> Nothing+  }++ruleNumerals5 :: Rule+ruleNumerals5 = Rule+  { name = "numbers 62..69 .. 92..99"+  , pattern =+    [ oneOf [60, 80]+    , numberBetween 2 20+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleNumeralMap :: HashMap Text Integer+ruleNumeralMap = HashMap.fromList+  [ ( "zero"     , 0 )+  , ( "z\x00e9ro", 0 )+  , ( "un"       , 1 )+  , ( "une"      , 1 )+  , ( "deux"     , 2 )+  , ( "trois"    , 3 )+  , ( "quatre"   , 4 )+  , ( "cinq"     , 5 )+  , ( "six"      , 6 )+  , ( "sept"     , 7 )+  , ( "huit"     , 8 )+  , ( "neuf"     , 9 )+  , ( "dix"      , 10 )+  , ( "onze"     , 11 )+  , ( "douze"    , 12 )+  , ( "treize"   , 13 )+  , ( "quatorze" , 14 )+  , ( "quinze"   , 15 )+  , ( "seize"    , 16 )+  ]++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..16)"+  , pattern =+    [ regex "(z(e|\x00e9)ro|une?|deux|trois|quatre|cinq|six|sept|huit|neuf|dix|onze|douze|treize|quatorze|quinze|seize)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) ruleNumeralMap >>= integer+      _ -> Nothing+  }++ruleNumeral3 :: Rule+ruleNumeral3 = Rule+  { name = "number (17..19)"+  , pattern =+    [ numberWith TNumeral.value (== 10)+    , numberBetween 7 10+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ 10 + v+      _ -> Nothing+  }++ruleNumerals3 :: Rule+ruleNumerals3 = Rule+  { name = "numbers 61 71"+  , pattern =+    [ numberWith TNumeral.value (== 60)+    , regex "-?et-?"+    , oneOf [1, 11]+    ]+  , prod = \tokens -> case tokens of+      (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$\x20ac\x00a2\x00a3]|$)"+    ]+  , 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+  }++ruleNumeral4 :: Rule+ruleNumeral4 = Rule+  { name = "number 80"+  , pattern =+    [ regex "quatre"+    , regex "vingts?"+    ]+  , prod = \_ -> integer 80+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 21 31 41 51"+  , pattern =+    [ oneOf [20, 50, 40, 30]+    , regex "et"+    , numberWith TNumeral.value (== 1)+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> 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:_)):+       _) -> let fmt = Text.replace (Text.singleton '.') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(cent|mille|millions?|milliards?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "cent"      -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "mille"     -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "millions"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milliard"  -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "milliards" -> double 1e9 >>= withGrain 9 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeral2+  , ruleNumeral3+  , ruleNumeral4+  , ruleNumerals+  , ruleNumerals2+  , ruleNumerals3+  , ruleNumerals4+  , ruleNumerals5+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSum+  , ruleMultiply+  ]
+ Duckling/Numeral/GA/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "a náid"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "aon"+             , "a haon"+             , "Amháin"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "Fiche"+             ]+  ]
+ Duckling/Numeral/GA/Rules.hs view
@@ -0,0 +1,256 @@+-- 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 #-}++module Duckling.Numeral.GA.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|m(\x00ed|i)neas(\\sa)?\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ v * (-1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleNumerals2 :: Rule+ruleNumerals2 = Rule+  { name = "numbers, 1-10"+  , pattern =+    [ regex "(aon|dh(\x00e1|a)|tr(\x00ed|i)|ceithre|c(\x00fa|u)ig|seacht|s(\x00e9|e)|ocht|naoi|deich)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "aon" -> integer 1+        "dha" -> integer 2+        "dh\x00e1" -> integer 2+        "tr\x00ed" -> integer 3+        "tri" -> integer 3+        "ceithre" -> integer 4+        "cuig" -> integer 5+        "c\x00faig" -> integer 5+        "s\x00e9" -> integer 6+        "se" -> integer 6+        "seacht" -> integer 7+        "ocht" -> integer 8+        "naoi" -> integer 9+        "deich" -> integer 10+        _ -> Nothing+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleDag :: Rule+ruleDag = Rule+  { name = "déag"+  , pattern =+    [ regex "d(\x00e9|e)ag"+    ]+  , prod = \_ -> integer 10+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++ruleOldVigesimalNumeralsS :: Rule+ruleOldVigesimalNumeralsS = Rule+  { name = "old vigesimal numbers, 20s"+  , pattern =+    [ regex "is (dh?(\x00e1|a) fhichead|tr(\x00ed|i) fichid|ceithre fichid)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "d\x00e1 fhichead" -> integer 40+        "da fhichead" -> integer 40+        "dh\x00e1 fhichead" -> integer 40+        "dha fhichead" -> integer 40+        "tr\x00ed fichid" -> integer 60+        "tri fichid" -> integer 60+        "ceithre fichid" -> integer 80+        _ -> Nothing+      _ -> Nothing+  }++ruleOldVigesimalNumeralsS2 :: Rule+ruleOldVigesimalNumeralsS2 = Rule+  { name = "old vigesimal numbers, 20s + 10"+  , pattern =+    [ regex "d(\x00e9|e)ag is (fiche|dh?(\x00e1|a) fhichead|tr(\x00ed|i) fichid|ceithre fichid)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "fiche" -> integer 30+        "d\x00e1 fhichead" -> integer 50+        "da fhichead" -> integer 50+        "dh\x00e1 fhichead" -> integer 50+        "dha fhichead" -> integer 50+        "tr\x00ed fichid" -> integer 70+        "tri fichid" -> integer 70+        "ceithre fichid" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleAmhin :: Rule+ruleAmhin = Rule+  { name = "amháin"+  , pattern =+    [ regex "amh(\x00e1|a)in"+    ]+  , prod = \_ -> integer 1+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers, 20-90"+  , pattern =+    [ regex "(fiche|tr(\x00ed|i)ocha|daichead|caoga|seasca|seacht(\x00f3|o)|ocht(\x00f3|o)|n(\x00f3|o)cha)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "fiche" -> integer 20+        "triocha" -> integer 30+        "tr\x00edocha" -> integer 30+        "daichead" -> integer 40+        "caoga" -> integer 50+        "seasca" -> integer 60+        "seachto" -> integer 70+        "seacht\x00f3" -> integer 70+        "ochto" -> integer 80+        "ocht\x00f3" -> integer 80+        "n\x00f3cha" -> integer 90+        "nocha" -> integer 90+        _ -> Nothing+      _ -> 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.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleCountNumerals :: Rule+ruleCountNumerals = Rule+  { name = "count numbers"+  , pattern =+    [ regex "a (n(\x00e1|a)id|haon|d(\x00f3|o)|tr(\x00ed|i)|ceathair|c(\x00fa|u)ig|s(\x00e9|e)|seacht|hocht|naoi|deich)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "naid" -> integer 0+        "n\x00e1id" -> integer 0+        "haon" -> integer 1+        "d\x00f3" -> integer 2+        "do" -> integer 2+        "tr\x00ed" -> integer 3+        "tri" -> integer 3+        "ceathair" -> integer 4+        "cuig" -> integer 5+        "c\x00faig" -> integer 5+        "s\x00e9" -> integer 6+        "se" -> integer 6+        "seacht" -> integer 7+        "hocht" -> integer 8+        "naoi" -> integer 9+        "deich" -> integer 10+        _ -> Nothing+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAmhin+  , ruleCountNumerals+  , ruleDag+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumerals+  , ruleNumerals2+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , ruleOldVigesimalNumeralsS+  , ruleOldVigesimalNumeralsS2+  ]
+ Duckling/Numeral/HE/Corpus.hs view
@@ -0,0 +1,94 @@+-- 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.HE.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HE}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "אפס"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "אחד"+             , "אחת"+             , "יחיד"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "שתיים"+             , "שניים"+             , "זוג"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "שלושים ושלוש"+             , "שלושים ושלושה"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "ארבעה עשר"+             , "ארבע עשרה"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "ששה עשר"+             , "שש עשרה"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "שבעה עשר"+             , "שבע עשרה"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "שמונה עשר"+             , "שמונה עשרה"+             ]+  , 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 3000000)+             [ "3000000"+             , "3,000,000"+             ]+  , examples (NumeralValue 1200000)+             [ "1,200,000"+             , "1200000"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1,200,000"+             , "-1200000"+             , "מינוס 1,200,000"+             ]+  ]
+ Duckling/Numeral/HE/Rules.hs view
@@ -0,0 +1,389 @@+-- 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 #-}++module Duckling.Numeral.HE.Rules+  ( rules ) where++import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+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++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer 4"+  , pattern =+    [ regex "(\x05d0\x05e8\x05d1\x05e2(\x05d4)?)"+    ]+  , prod = \_ -> integer 4+  }++ruleIntersectNumerals :: Rule+ruleIntersectNumerals = Rule+  { name = "intersect numbers"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "\x05d5"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleCompositeTens :: Rule+ruleCompositeTens = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [ 20, 30..90 ]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = tens}):+       Token Numeral (NumeralData {TNumeral.value = units}):+       _) -> double $ tens + units+      _ -> Nothing+  }++ruleCompositeTensWithAnd :: Rule+ruleCompositeTensWithAnd = Rule+  { name = "integer 21..99 (with and)"+  , pattern =+    [ oneOf [ 20, 30..90 ]+    , regex "\x05d5"+    , 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"+  , pattern =+    [ regex "-|\x05de\x05d9\x05e0\x05d5\x05e1"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleInteger10 :: Rule+ruleInteger10 = Rule+  { name = "integer 9"+  , pattern =+    [ regex "(\x05ea\x05e9\x05e2(\x05d4)?)"+    ]+  , prod = \_ -> integer 9+  }++ruleInteger15 :: Rule+ruleInteger15 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(\x05e2\x05e9\x05e8\x05d9\x05dd|\x05e9\x05dc\x05d5\x05e9\x05d9\x05dd|\x05d0\x05e8\x05d1\x05e2\x05d9\x05dd|\x05d7\x05de\x05d9\x05e9\x05d9\x05dd|\x05e9\x05d9\x05e9\x05d9\x05dd|\x05e9\x05d1\x05e2\x05d9\x05dd|\x05e9\x05de\x05d5\x05e0\x05d9\x05dd|\x05ea\x05e9\x05e2\x05d9\x05dd)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x05e2\x05e9\x05e8\x05d9\x05dd" -> integer 20+        "\x05e9\x05dc\x05d5\x05e9\x05d9\x05dd" -> integer 30+        "\x05d0\x05e8\x05d1\x05e2\x05d9\x05dd" -> integer 40+        "\x05d7\x05de\x05d9\x05e9\x05d9\x05dd" -> integer 50+        "\x05e9\x05d9\x05e9\x05d9\x05dd" -> integer 60+        "\x05e9\x05d1\x05e2\x05d9\x05dd" -> integer 70+        "\x05e9\x05de\x05d5\x05e0\x05d9\x05dd" -> integer 80+        "\x05ea\x05e9\x05e2\x05d9\x05dd" -> integer 90+        _ -> Nothing+      _ -> 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 2"+  , pattern =+    [ regex "(\x05e9\x05ea\x05d9\x05d9\x05dd|\x05e9\x05e0\x05d9\x05d9\x05dd)"+    ]+  , prod = \_ -> integer 2+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "\x05d9\x05d7\x05d9\x05d3"+    ]+  , prod = \_ -> integer 1+  }++ruleInteger13 :: Rule+ruleInteger13 = Rule+  { name = "integer 12"+  , pattern =+    [ regex "(\x05e9\x05e0\x05d9\x05d9\x05dd \x05e2\x05e9\x05e8|\x05ea\x05e8\x05d9 \x05e2\x05e9\x05e8)"+    ]+  , prod = \_ -> integer 12+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer 5"+  , pattern =+    [ regex "(\x05d7\x05de(\x05e9|\x05d9\x05e9\x05d4))"+    ]+  , prod = \_ -> integer 5+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(\x05de\x05d0(\x05d4|\x05d5\x05ea)|\x05d0\x05dc(\x05e3|\x05e4\x05d9\x05dd)|\x05de\x05d9\x05dc\x05d9\x05d5(\x05df|\x05e0\x05d9\x05dd))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "\x05de\x05d0\x05d4"                               ->+          double 1e2 >>= withGrain 2 >>= withMultipliable+        "\x05de\x05d0\x05d5\x05ea"                         ->+          double 1e2 >>= withGrain 2 >>= withMultipliable+        "\x05d0\x05dc\x05e3"                               ->+          double 1e3 >>= withGrain 3 >>= withMultipliable+        "\x05d0\x05dc\x05e4\x05d9\x05dd"                   ->+          double 1e3 >>= withGrain 3 >>= withMultipliable+        "\x05de\x05d9\x05dc\x05d9\x05d5\x05df"             ->+          double 1e6 >>= withGrain 6 >>= withMultipliable+        "\x05de\x05d9\x05dc\x05d9\x05d5\x05e0\x05d9\x05dd" ->+          double 1e6 >>= withGrain 6 >>= withMultipliable+        _          -> Nothing+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer 6"+  , pattern =+    [ regex "(\x05e9\x05e9(\x05d4)?)"+    ]+  , prod = \_ -> integer 6+  }++ruleInteger14 :: Rule+ruleInteger14 = Rule+  { name = "integer 11..19"+  , pattern =+    [ numberBetween 1 10+    , numberWith TNumeral.value (== 10)+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 7"+  , pattern =+    [ regex "(\x05e9\x05d1\x05e2(\x05d4)?)"+    ]+  , prod = \_ -> integer 7+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple"+  , pattern =+    [ regex "\x05d6\x05d5\x05d2( \x05e9\x05dc)?"+    ]+  , prod = \_ -> integer 2+  }++ruleInteger16 :: Rule+ruleInteger16 = Rule+  { name = "integer 101..999"+  , pattern =+    [ oneOf [300, 600, 500, 100, 800, 200, 900, 700, 400]+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger9 :: Rule+ruleInteger9 = Rule+  { name = "integer 8"+  , pattern =+    [ regex "(\x05e9\x05de\x05d5\x05e0\x05d4)"+    ]+  , prod = \_ -> integer 8+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "(\x05d0\x05e4\x05e1|\x05db\x05dc\x05d5\x05dd)"+    ]+  , prod = \_ -> integer 0+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 3"+  , pattern =+    [ regex "(\x05e9\x05dc\x05d5\x05e9(\x05d4)?)"+    ]+  , prod = \_ -> integer 3+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 1"+  , pattern =+    [ regex "(\x05d0\x05d7\x05d3|\x05d0\x05d7\x05ea)"+    ]+  , prod = \_ -> integer 1+  }++ruleInteger11 :: Rule+ruleInteger11 = Rule+  { name = "integer 10"+  , pattern =+    [ regex "(\x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> integer 10+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "\x05e0\x05e7\x05d5\x05d3\x05d4"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleCommas :: Rule+ruleCommas = Rule+  { name = "comma-separated numbers"+  , pattern =+    [ regex "(\\d+(,\\d\\d\\d)+(\\.\\d+)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCommas+  , ruleCompositeTens+  , ruleCompositeTensWithAnd+  , ruleCouple+  , ruleDecimalNumeral+  , ruleInteger+  , ruleInteger10+  , ruleInteger11+  , ruleInteger13+  , ruleInteger14+  , ruleInteger15+  , ruleInteger16+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleInteger9+  , ruleIntegerNumeric+  , ruleIntersectNumerals+  , ruleIntersectWithAnd+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , rulePowersOfTen+  , ruleSingle+  ]
+ Duckling/Numeral/HR/Corpus.hs view
@@ -0,0 +1,127 @@+-- 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.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nula"+             , "nista"+             , "ništa"+             , "nistica"+             , "ništica"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "jedan"+             , "sam"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "dva"+             , "par"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "trideset i tri"+             , "trideset tri"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "cetrnaest"+             , "četrnaest"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "šesnaest"+             , "sesnaest"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "sedamnaest"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "osamnaest"+             ]+  , examples (NumeralValue 1.1)+             [ "1,1"+             , "jedan cijela jedan"+             , "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"+             , "minus 1.200.000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tisuća"+             , "pet tisuća"+             , "pet tisuca"+             ]+  , examples (NumeralValue 122)+             [ "stotinu dvadeset dva"+             ]+  , examples (NumeralValue 200000)+             [ "dvjesto tisuća"+             , "dvjesto tisuca"+             , "dvije stotine tisuca"+             , "dvije stotine tisuća"+             ]+  , examples (NumeralValue 21011)+             [ "dvadeset i jedna tisuca jedanaest"+             , "dvadeset i jedna tisuća jedanaest"+             ]+  , examples (NumeralValue 721012)+             [ "sedam stotina dvadeset jedna tisuća dvanaest"+             , "sedam stotina dvadeset jedna tisuca dvanaest"+             ]+  ]
+ Duckling/Numeral/HR/Rules.hs view
@@ -0,0 +1,383 @@+-- 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 #-}++module Duckling.Numeral.HR.Rules+  ( rules ) where++import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+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++ruleNumbersPrefixWithNegativeOrMinus :: Rule+ruleNumbersPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus|negativ"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "nekoliko"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "deset|cener"+    ]+  , 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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleDecimalNumber :: Rule+ruleDecimalNumber = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*,\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> parseDecimal False match+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer (100..900)"+  , pattern =+    [ regex "(sto|dvjest(o|a)|tristo|(c|\x010d)etiristo|petsto|(\x0161|s)esto|sedamsto|osamsto|devetsto)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "sto" -> integer 100+        "dvjesta" -> integer 200+        "dvjesto" -> integer 200+        "tristo" -> integer 300+        "cetiristo" -> integer 400+        "\269etiristo" -> integer 400+        "petsto" -> integer 500+        "\353esto" -> integer 600+        "sesto" -> integer 600+        "sedamsto" -> integer 700+        "osamsto" -> integer 800+        "devetsto" -> integer 900+        _ -> Nothing+      _ -> Nothing+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "sam"+    ]+  , prod = \_ -> integer 1 >>= withGrain 1+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(stotin(u|a|e)|tisu(c|\x0107)(a|u|e)|milij(u|o)na?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "stotinu" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "stotina" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "stotine" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tisuca" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisucu" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisuce" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisu\263a" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisu\263u" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tisu\263e" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "milijun" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milijuna" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milijon" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milijona" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++ruleNumbersI :: Rule+ruleNumbersI = Rule+  { name = "numbers i"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , regex "i"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleNumbersSuffixesKMG :: Rule+ruleNumbersSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++ruleAPair :: Rule+ruleAPair = Rule+  { name = "a pair"+  , pattern =+    [ regex "par"+    ]+  , prod = \_ -> integer 2 >>= withGrain 1+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "tucet?"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(ni(s|\x0161)ta|ni(s|\x0161)tica|nula|jedanaest|dvanaest|trinaest|jeda?n(a|u|o(ga?)?)?|dv(i?je)?(a|o)?(ma)?|tri(ma)?|(\x010d|c)etiri|(\x010d|c)etrnaest|petnaest|pet|(s|\x0161)esnaest|(\x0161|s)est|sedamnaest|sedam|osamnaest|osam|devetnaest|devet)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "ni\353ta" -> integer 0+        "ni\353tica" -> integer 0+        "nistica" -> integer 0+        "nista" -> integer 0+        "nula" -> integer 0+        "jednoga" -> integer 1+        "jedna" -> integer 1+        "jednog" -> integer 1+        "jednu" -> integer 1+        "jedan" -> integer 1+        "dvoma" -> integer 2+        "dvije" -> integer 2+        "dvje" -> integer 2+        "dva" -> integer 2+        "dvama" -> integer 2+        "trima" -> integer 3+        "tri" -> integer 3+        "\269etiri" -> integer 4+        "cetiri" -> integer 4+        "pet" -> integer 5+        "\353est" -> integer 6+        "sedam" -> integer 7+        "osam" -> integer 8+        "devet" -> integer 9+        "jedanaest" -> integer 11+        "dvanaest" -> integer 12+        "trinaest" -> integer 13+        "cetrnaest" -> integer 14+        "\269etrnaest" -> integer 14+        "petnaest" -> integer 15+        "\353esnaest" -> integer 16+        "sesnaest" -> integer 16+        "sedamnaest" -> integer 17+        "osamnaest" -> integer 18+        "devetnaest" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(dvadeset|trideset|(c|\x010d)etrdeset|pedeset|(\x0161|s)esdeset|sedamdeset|osamdeset|devedeset)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "dvadeset" -> integer 20+        "trideset" -> integer 30+        "cetrdeset" -> integer 40+        "\269etrdeset" -> integer 40+        "pedeset" -> integer 50+        "sesdeset" -> integer 60+        "\353esdeset" -> integer 60+        "sedamdeset" -> integer 70+        "osamdeset" -> integer 80+        "devedeset" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumbers :: Rule+ruleNumbers = Rule+  { name = "numbers 100..999"+  , pattern =+    [ numberBetween 1 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+      _ -> Nothing+  }++ruleNumberDotNumber :: Rule+ruleNumberDotNumber = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "cijela|to(c|\x010d)ka|zarez"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ."+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace (Text.singleton '.') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAPair+  , ruleDecimalNumber+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4 , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleMultiply+  , ruleNumberDotNumber+  , ruleNumbers+  , ruleNumbersI+  , ruleNumbersPrefixWithNegativeOrMinus+  , ruleNumbersSuffixesKMG+  , rulePowersOfTen+  , ruleSingle+  , ruleSum+  , ruleTen+  ]
+ Duckling/Numeral/Helpers.hs view
@@ -0,0 +1,128 @@+-- 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 #-}++module Duckling.Numeral.Helpers+  ( decimalsToDouble+  , double+  , integer+  , multiply+  , numberBetween+  , numberWith+  , oneOf+  , parseDouble+  , parseInt+  , withGrain+  , withMultipliable+  , parseDecimal,+  ) where++import qualified Data.Attoparsec.Text as Atto+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Types+import Duckling.Types hiding (value)++zeroT :: Text+zeroT = Text.singleton '0'++dot :: Text+dot = Text.singleton '.'++comma :: Text+comma = Text.singleton ','++parseInt :: Text -> Maybe Int+parseInt =+  either (const Nothing) Just . Atto.parseOnly (Atto.signed Atto.decimal)++-- | Add leading 0 when leading . for double parsing to succeed+parseDouble :: Text -> Maybe Double+parseDouble s+  | Text.head s == '.' = go $ Text.append zeroT s+  | otherwise = go s+  where go = either (const Nothing) Just . Atto.parseOnly Atto.double++-- | 77 -> .77+-- | Find the first power of ten larger that the actual number+-- | Use it to divide x+decimalsToDouble :: Double -> Double+decimalsToDouble x =+  let xs = filter (\y -> x - y < 0)+         . take 10+         . iterate (*10) $ 1 in+    case xs of+      [] -> 0+      (multiplier : _) -> x / multiplier++-- -----------------------------------------------------------------+-- Patterns++numberWith :: (NumeralData -> t) -> (t -> Bool) -> PatternItem+numberWith f pred = Predicate $ \x ->+  case x of+    (Token Numeral x@NumeralData{}) -> pred (f x)+    _ -> False++numberBetween :: Double -> Double -> PatternItem+numberBetween low up = Predicate $ \x ->+  case x of+    (Token Numeral NumeralData {value = v, multipliable = False}) ->+      low <= v && v < up+    _ -> False++oneOf :: [Double] -> PatternItem+oneOf vs = Predicate $ \x ->+  case x of+    (Token Numeral NumeralData {value = v}) -> elem v vs+    _ -> False++-- -----------------------------------------------------------------+-- Production++withMultipliable :: Token -> Maybe Token+withMultipliable (Token Numeral x@NumeralData{}) =+  Just . Token Numeral $ x {multipliable = True}+withMultipliable _ = Nothing++withGrain :: Int -> Token -> Maybe Token+withGrain g (Token Numeral x@NumeralData{}) =+  Just . Token Numeral $ x {grain = Just g}+withGrain _ _ = Nothing++double :: Double -> Maybe Token+double x = Just . Token Numeral $ NumeralData+  { value = x+  , grain = Nothing+  , multipliable = False+  }++integer :: Integer -> Maybe Token+integer = double . fromIntegral++multiply :: Token -> Token -> Maybe Token+multiply+  (Token Numeral (NumeralData {value = v1}))+  (Token Numeral (NumeralData {value = v2, grain = g})) = case g of+  Nothing -> double $ v1 * v2+  Just grain | v2 > v1 -> double (v1 * v2) >>= withGrain grain+             | otherwise -> Nothing+multiply _ _ = Nothing++parseDecimal :: Bool -> Text -> Maybe Token+parseDecimal isDot match+  | isDot = parseDouble match >>= double+  | otherwise =+    parseDouble (Text.replace comma dot match)+    >>= double
+ Duckling/Numeral/ID/Corpus.hs view
@@ -0,0 +1,118 @@+-- 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.ID.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ID}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nol"+             , "kosong"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "satu"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "Dua"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "sepuluh"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "tiga puluh tiga"+             , "0033"+             ]+  , examples (NumeralValue 100)+             [ "100"+             , "seratus"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "tujuh belas"+             ]+  , examples (NumeralValue 28)+             [ "28"+             , "dua puluh delapan"+             ]+  , 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"+             , "minus 1.200.000"+             , "negatif 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             , "-0,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 ribu"+             , "lima ribu"+             ]+  , examples (NumeralValue 122)+             [ "seratus dua puluh dua"+             ]+  , examples (NumeralValue 200000)+             [ "dua ratus ribu"+             ]+  , examples (NumeralValue 10011)+             [ "sepuluh ribu sebelas"+             ]+  , examples (NumeralValue 721012)+             [ "tujuh ratus dua puluh satu ribu dua belas"+             ]+  , examples (NumeralValue 31256721)+             [ "tiga puluh satu juta dua ratus lima puluh enam ribu tujuh ratus dua puluh satu"+             ]+  ]
+ Duckling/Numeral/ID/Rules.hs view
@@ -0,0 +1,274 @@+-- 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 #-}++module Duckling.Numeral.ID.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleTeen :: Rule+ruleTeen = Rule+  { name = "teen"+  , pattern =+    [ numberBetween 2 10+    , regex "belas"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 10+      _ -> Nothing+  }++ruleNumeralCommaNumeral :: Rule+ruleNumeralCommaNumeral = Rule+  { name = "number comma number"+  , pattern =+    [ dimension Numeral+    , regex "koma"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus\\s?|negatif\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "(se)?puluh"+    ]+  , 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 dot = Text.singleton '.'+                 comma = Text.singleton ','+                 fmt = Text.replace comma dot $ Text.replace dot Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleSomefewcouple :: Rule+ruleSomefewcouple = Rule+  { name = "some/few/couple"+  , pattern =+    [ regex "beberapa"+    ]+  , prod = \_ -> integer 3+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(se)?(ratus|ribu|juta)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (_:match:_)):_) -> case Text.toLower match of+        "ratus"-> double 1e2 >>= withGrain 2 >>= withMultipliable+        "ribu" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "juta" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _      -> Nothing+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "(se)?lusin"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..9 11)"+  , pattern =+    [ regex "(kosong|nol|satu|dua|tiga|empat|lima|enam|tujuh|delapan|sembilan|sebelas)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "kosong" -> integer 0+        "nol" -> integer 0+        "satu" -> integer 1+        "dua" -> integer 2+        "tiga" -> integer 3+        "empat" -> integer 4+        "lima" -> integer 5+        "enam" -> integer 6+        "tujuh" -> integer 7+        "delapan" -> integer 8+        "sembilan" -> integer 9+        "sebelas" -> integer 11+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 20..90"+  , pattern =+    [ numberBetween 2 10+    , numberWith TNumeral.value (== 10)+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2, TNumeral.grain = Just g}):+       _) -> double (v1 * v2) >>= withGrain g+      _ -> 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.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralCommaNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSomefewcouple+  , ruleTeen+  , ruleTen+  ]
+ Duckling/Numeral/IT/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.IT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = IT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nulla"+             , "zero"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "uno"+             , "Un"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "due"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "tre"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "quattro"+             ]+  , examples (NumeralValue 5)+             [ "5"+             , "cinque"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "sei"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "sette"+             ]+  , examples (NumeralValue 8)+             [ "8"+             , "otto"+             ]+  , examples (NumeralValue 9)+             [ "9"+             , "nove"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "dieci"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "trentatré"+             , "0033"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "Undici"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "dodici"+             ]+  , examples (NumeralValue 13)+             [ "13"+             , "tredici"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "quattordici"+             ]+  , examples (NumeralValue 15)+             [ "15"+             , "quindici"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "sedici"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "diciassette"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "diciotto"+             ]+  , examples (NumeralValue 19)+             [ "19"+             , "diciannove"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "venti"+             ]+  , 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"+             , "meno 1.200.000"+             , "negativo 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  ]
+ Duckling/Numeral/IT/Rules.hs view
@@ -0,0 +1,324 @@+-- 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 #-}++module Duckling.Numeral.IT.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|meno|negativo"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> 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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleNumeral2 :: Rule+ruleNumeral2 = Rule+  { name = "number (20..90)"+  , pattern =+    [ regex "(venti|trenta|quaranta|cinquanta|sessanta|settanta|ottanta|novanta)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "venti" -> integer 20+        "trenta" -> integer 30+        "quaranta" -> integer 40+        "cinquanta" -> integer 50+        "sessanta" -> integer 60+        "settanta" -> integer 70+        "ottanta" -> integer 80+        "novanta" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..19)"+  , pattern =+    [ regex "(zero|nulla|niente|uno|due|tredici|tre|quattro|cinque|sei|sette|otto|nove|dieci|undici|dodici|quattordici|quindici|sedici|diciassette|diciotto|diciannove|un)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "zero" -> integer 0+        "niente" -> integer 0+        "nulla" -> integer 0+        "un" -> integer 1+        "uno" -> integer 1+        "due" -> integer 2+        "tre" -> integer 3+        "quattro" -> integer 4+        "cinque" -> integer 5+        "sei" -> integer 6+        "sette" -> integer 7+        "otto" -> integer 8+        "nove" -> integer 9+        "dieci" -> integer 10+        "undici" -> integer 11+        "dodici" -> integer 12+        "tredici" -> integer 13+        "quattordici" -> integer 14+        "quindici" -> integer 15+        "sedici" -> integer 16+        "diciassette" -> integer 17+        "diciotto" -> integer 18+        "diciannove" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral5 :: Rule+ruleNumeral5 = Rule+  { name = "number 100..1000 "+  , pattern =+    [ regex "(due|tre|quattro|cinque|sei|sette|otto|nove)?cento|mil(a|le)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "cento" -> integer 100+        "duecento" -> integer 200+        "trecento" -> integer 300+        "quattrocento" -> integer 400+        "cinquecento" -> integer 500+        "seicento" -> integer 600+        "settecento" -> integer 700+        "ottocento" -> integer 800+        "novecento" -> integer 900+        " mila" -> integer 1000+        "mille" -> integer 1000+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral3 :: Rule+ruleNumeral3 = 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 "e"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (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\\$\x20ac]|$)"+    ]+  , 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+  }++ruleNumeral4 :: Rule+ruleNumeral4 = Rule+  { name = "number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)"+  , pattern =+    [ regex "((venti|trenta|quaranta|cinquanta|sessanta|settanta|ottanta|novanta)(due|tre|tr\x00e9|quattro|cinque|sei|sette|nove))|((vent|trent|quarant|cinquant|sessant|settant|ottant|novant)(uno|otto))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "ventuno" -> integer 21+        "ventidue" -> integer 22+        "ventitre" -> integer 23+        "ventitr\x00e9" -> integer 23+        "ventiquattro" -> integer 24+        "venticinque" -> integer 25+        "ventisei" -> integer 26+        "ventisette" -> integer 27+        "ventotto" -> integer 28+        "ventinove" -> integer 29+        "trentuno" -> integer 31+        "trentadue" -> integer 32+        "trentatre" -> integer 33+        "trentatr\x00e9" -> integer 33+        "trentaquattro" -> integer 34+        "trentacinque" -> integer 35+        "trentasei" -> integer 36+        "trentasette" -> integer 37+        "trentotto" -> integer 38+        "trentanove" -> integer 39+        "quarantuno" -> integer 41+        "quarantadue" -> integer 42+        "quarantatre" -> integer 43+        "quarantatr\x00e9" -> integer 43+        "quarantaquattro" -> integer 44+        "quarantacinque" -> integer 45+        "quarantasei" -> integer 46+        "quarantasette" -> integer 47+        "quarantotto" -> integer 48+        "quarantanove" -> integer 49+        "cinquantuno" -> integer 51+        "cinquantadue" -> integer 52+        "cinquantatre" -> integer 53+        "cinquantatr\x00e9" -> integer 53+        "cinquantaquattro" -> integer 54+        "cinquantacinque" -> integer 55+        "cinquantasei" -> integer 56+        "cinquantasette" -> integer 57+        "cinquantotto" -> integer 58+        "cinquantanove" -> integer 59+        "sessantuno" -> integer 61+        "sessantadue" -> integer 62+        "sessantatr\x00e9" -> integer 63+        "sessantatre" -> integer 63+        "sessantaquattro" -> integer 64+        "sessantacinque" -> integer 65+        "sessantasei" -> integer 66+        "sessantasette" -> integer 67+        "sessantotto" -> integer 68+        "sessantanove" -> integer 69+        "settantuno" -> integer 71+        "settantadue" -> integer 72+        "settantatr\x00e9" -> integer 73+        "settantatre" -> integer 73+        "settantaquattro" -> integer 74+        "settantacinque" -> integer 75+        "settantasei" -> integer 76+        "settantasette" -> integer 77+        "settantotto" -> integer 78+        "settantanove" -> integer 79+        "ottantuno" -> integer 81+        "ottantadue" -> integer 82+        "ottantatr\x00e9" -> integer 83+        "ottantatre" -> integer 83+        "ottantaquattro" -> integer 84+        "ottantacinque" -> integer 85+        "ottantasei" -> integer 86+        "ottantasette" -> integer 87+        "ottantotto" -> integer 88+        "ottantanove" -> integer 89+        "novantuno" -> integer 91+        "novantadue" -> integer 92+        "novantatre" -> integer 93+        "novantatr\x00e9" -> integer 93+        "novantaquattro" -> integer 94+        "novantacinque" -> integer 95+        "novantasei" -> integer 96+        "novantasette" -> integer 97+        "novantotto" -> integer 98+        "novantanove" -> integer 99+        _ -> Nothing+      _ -> Nothing+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 200..999"+  , pattern =+    [ 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}):+       Token Numeral (NumeralData {TNumeral.value = v3}):+       _) -> double $ v1 * v2 + v3+      _ -> 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.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeral2+  , ruleNumeral3+  , ruleNumeral4+  , ruleNumeral5+  , ruleNumerals+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/JA/Corpus.hs view
@@ -0,0 +1,109 @@+-- 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.JA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = JA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "零"+             , "ゼロ"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "一"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "三十三"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "十四"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "十六"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "十七"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "十八"+             ]+  , examples (NumeralValue 100)+             [ "100"+             , "百"+             ]+  , examples (NumeralValue 101)+             [ "101"+             , "百一"+             ]+  , examples (NumeralValue 200)+             [ "200"+             ]+  , 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"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5千"+             ]+  , examples (NumeralValue 20000)+             [ "2万"+             ]+  ]
+ Duckling/Numeral/JA/Rules.hs view
@@ -0,0 +1,373 @@+-- 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 #-}++module Duckling.Numeral.JA.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer (100)"+  , pattern =+    [ regex "\x767e"+    ]+  , prod = \_ -> integer 100+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|\x30de\x30a4\x30ca\x30b9\\s?|\x8ca0\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleInteger17 :: Rule+ruleInteger17 = Rule+  { name = "integer (0..10)"+  , pattern =+    [ regex "(\x30bc\x30ed|\x96f6|\x4e00|\x4e8c|\x4e09|\x56db|\x4e94|\x516d|\x4e03|\x516b|\x4e5d|\x5341)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x30bc\x30ed" -> integer 0+        "\x96f6" -> integer 0+        "\x4e00" -> integer 1+        "\x4e8c" -> integer 2+        "\x4e09" -> integer 3+        "\x56db" -> integer 4+        "\x4e94" -> integer 5+        "\x516d" -> integer 6+        "\x4e03" -> integer 7+        "\x516b" -> integer 8+        "\x4e5d" -> integer 9+        "\x5341" -> integer 10+        _ -> Nothing+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleInteger10 :: Rule+ruleInteger10 = Rule+  { name = "integer (1000..1999)"+  , pattern =+    [ regex "\x5343"+    , numberBetween 1 1000+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ v + 1000+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleInteger15 :: Rule+ruleInteger15 = Rule+  { name = "integer (20000..90000)"+  , pattern =+    [ numberBetween 2 10+    , regex "\x4e07"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 10000+      _ -> 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+  }++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "<number>个"+  , pattern =+    [ dimension Numeral+    , regex "\x4e2a"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> Just token+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ numberBetween 2 10+    , regex "\x5341"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 10+      _ -> Nothing+  }++ruleInteger13 :: Rule+ruleInteger13 = Rule+  { name = "integer (10000)"+  , pattern =+    [ regex "\x4e07"+    ]+  , prod = \_ -> integer 10000+  }++ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer (100..199)"+  , pattern =+    [ regex "\x767e"+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 100+      _ -> Nothing+  }++ruleInteger12 :: Rule+ruleInteger12 = Rule+  { name = "integer 2001..9999"+  , pattern =+    [ oneOf [3000, 9000, 7000, 8000, 2000, 4000, 6000, 5000]+    , numberBetween 1 1000+    ]+  , prod = \tokens -> case tokens of+      (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 "(k|m|g|\x5343|\x4e07)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+          "k"      -> double $ v * 1e3+          "\x5343" -> double $ v * 1e3+          "\x4e07" -> double $ v * 1e4+          "m"      -> double $ v * 1e6+          "g"      -> double $ v * 1e9+          _ -> Nothing+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer (200..900)"+  , pattern =+    [ numberBetween 2 10+    , regex "\x767e"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 100+      _ -> Nothing+  }++ruleInteger14 :: Rule+ruleInteger14 = Rule+  { name = "integer (10000..19999)"+  , pattern =+    [ regex "\x4e07"+    , numberBetween 1 10000+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double $ v + 10000+      _ -> Nothing+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 201..999"+  , pattern =+    [ oneOf [300, 600, 500, 800, 200, 900, 700, 400]+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger16 :: Rule+ruleInteger16 = Rule+  { name = "integer 20001..99999"+  , pattern =+    [ oneOf [20000, 40000, 80000, 60000, 30000, 70000, 90000, 50000]+    , numberBetween 1 10000+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger9 :: Rule+ruleInteger9 = Rule+  { name = "integer (1000)"+  , pattern =+    [ regex "\x5343"+    ]+  , prod = \_ -> integer 1000+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..10)"+  , pattern =+    [ regex "\x30bc\x30ed|\x96f6|\x4e00|\x4e8c|\x4e09|\x56db|\x4e94|\x516d|\x4e03|\x516b|\x4e5d|\x5341"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x96f6" -> integer 0+        "\x30bc\x30ed" -> integer 0+        "\x4e00" -> integer 1+        "\x4e8c" -> integer 2+        "\x4e09" -> integer 3+        "\x56db" -> integer 4+        "\x4e94" -> integer 5+        "\x516d" -> integer 6+        "\x4e03" -> integer 7+        "\x516b" -> integer 8+        "\x4e5d" -> integer 9+        "\x5341" -> integer 10+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (11..19)"+  , pattern =+    [ regex "\x5341"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 10+      _ -> Nothing+  }++ruleInteger11 :: Rule+ruleInteger11 = Rule+  { name = "integer (2000..9000)"+  , pattern =+    [ numberBetween 2 10+    , regex "\x5343"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 1000+      _ -> 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.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger10+  , ruleInteger11+  , ruleInteger12+  , ruleInteger13+  , ruleInteger14+  , ruleInteger15+  , ruleInteger16+  , ruleInteger17+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleInteger9+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/KO/Corpus.hs view
@@ -0,0 +1,194 @@+-- 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.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "영"+             , "빵"+             , "공"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "일"+             , "하나"+             , "한"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "십"+             , "열"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "십일"+             , "열하나"+             , "십하나"+             , "열한"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "이십"+             , "스물"+             ]+  , examples (NumeralValue 35)+             [ "35"+             , "삼십오"+             , "서른다섯"+             ]+  , examples (NumeralValue 47)+             [ "47"+             , "사십칠"+             , "마흔일곱"+             ]+  , examples (NumeralValue 52)+             [ "52"+             , "오십이"+             , "쉰둘"+             , "쉰두"+             ]+  , examples (NumeralValue 69)+             [ "69"+             , "육십구"+             , "예순아홉"+             ]+  , examples (NumeralValue 71)+             [ "71"+             , "칠십일"+             , "일흔하나"+             , "일흔한"+             ]+  , examples (NumeralValue 84)+             [ "84"+             , "팔십사"+             , "여든넷"+             ]+  , examples (NumeralValue 93)+             [ "93"+             , "구십삼"+             , "아흔셋"+             ]+  , examples (NumeralValue 100)+             [ "100"+             , "백"+             ]+  , examples (NumeralValue 123)+             [ "123"+             , "백이십삼"+             ]+  , examples (NumeralValue 579)+             [ "579"+             , "오백칠십구"+             ]+  , examples (NumeralValue 1000)+             [ "1000"+             , "천"+             ]+  , examples (NumeralValue 1723)+             [ "1723"+             , "천칠백이십삼"+             ]+  , examples (NumeralValue 5619)+             [ "5619"+             , "오천육백십구"+             ]+  , examples (NumeralValue 10000)+             [ "10000"+             , "만"+             , "일만"+             ]+  , examples (NumeralValue 12345)+             [ "12345"+             , "만이천삼백사십오"+             , "일만이천삼백사십오"+             ]+  , examples (NumeralValue 58194)+             [ "58194"+             , "오만팔천백구십사"+             ]+  , examples (NumeralValue 581900)+             [ "581900"+             , "오십팔만천구백"+             ]+  , examples (NumeralValue 5819014)+             [ "5819014"+             , "오백팔십일만구천십사"+             ]+  , examples (NumeralValue 58190148)+             [ "58190148"+             , "오천팔백십구만백사십팔"+             ]+  , examples (NumeralValue 100000000)+             [ "100000000"+             , "일억"+             ]+  , examples (NumeralValue 274500000000)+             [ "274500000000"+             , "이천칠백사십오억"+             ]+  , examples (NumeralValue 100000002)+             [ "100000002"+             , "일억이"+             ]+  , examples (NumeralValue 27350000)+             [ "27350000"+             , "이천칠백삼십오만"+             ]+  , examples (NumeralValue 3235698120)+             [ "3235698120"+             , "삼십이억삼천오백육십구만팔천백이십"+             ]+  , examples (NumeralValue 40234985729)+             [ "40234985729"+             , "사백이억삼천사백구십팔만오천칠백이십구"+             ]+  , examples (NumeralValue 701239801123)+             [ "701239801123"+             , "칠천십이억삼천구백팔십만천백이십삼"+             ]+  , examples (NumeralValue 3.4)+             [ "3.4"+             , "삼점사"+             ]+  , examples (NumeralValue 4123.3)+             [ "4123.3"+             , "사천백이십삼점삼"+             ]+  , examples (NumeralValue 1.23)+             [ "일점이삼"+             ]+  , examples (NumeralValue (-3))+             [ "-3"+             , "마이너스3"+             , "마이너스삼"+             , "마이너스 3"+             , "마이나스3"+             , "마이나스 3"+             ]+  , examples (NumeralValue 0.75)+             [ "3/4"+             , "사분의삼"+             ]+  ]
+ Duckling/Numeral/KO/Rules.hs view
@@ -0,0 +1,334 @@+-- 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 #-}++module Duckling.Numeral.KO.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleIntegerForOrdinals :: Rule+ruleIntegerForOrdinals = Rule+  { name = "integer (1..4) - for ordinals"+  , pattern =+    [ regex "(\xd55c|\xccab|\xb450|\xc138|\xb124)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xd55c" -> integer 1+        "\xccab" -> integer 1+        "\xb450" -> integer 2+        "\xc138" -> integer 3+        "\xb124" -> integer 4+        _ -> Nothing+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few 몇"+  , pattern =+    [ regex "\xba87"+    ]+  , prod = \_ -> integer 3+  }++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.singleton ',') 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 True match+      _ -> Nothing+  }++ruleFraction2 :: Rule+ruleFraction2 = 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 $ v1 / v2+      _ -> Nothing+  }++ruleNumeralsPrefixWithOr :: Rule+ruleNumeralsPrefixWithOr = Rule+  { name = "numbers prefix with -, 마이너스, or 마이나스"+  , pattern =+    [ regex "-|\xb9c8\xc774\xb108\xc2a4\\s?|\xb9c8\xc774\xb098\xc2a4\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleHalf :: Rule+ruleHalf = Rule+  { name = "half - 반"+  , pattern =+    [ regex "\xbc18"+    ]+  , prod = \_ -> double 0.5+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "\xc601|\xacf5|\xbe75"+    ]+  , prod = \_ -> integer 0+  }++ruleIntegerTypeAndOrdinals :: Rule+ruleIntegerTypeAndOrdinals = Rule+  { name = "integer (20..90) - TYPE 2 and ordinals"+  , pattern =+    [ regex "(\xc5f4|\xc2a4\xbb3c|\xc11c\xb978|\xb9c8\xd754|\xc270|\xc608\xc21c|\xc77c\xd754|\xc5ec\xb4e0|\xc544\xd754)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xc5f4" -> integer 10+        "\xc2a4\xbb3c" -> integer 20+        "\xc11c\xb978" -> integer 30+        "\xb9c8\xd754" -> integer 40+        "\xc270" -> integer 50+        "\xc608\xc21c" -> integer 60+        "\xc77c\xd754" -> integer 70+        "\xc5ec\xb4e0" -> integer 80+        "\xc544\xd754" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleIntegerType1 :: Rule+ruleIntegerType1 = Rule+  { name = "integer - TYPE 1"+  , pattern =+    [ regex "(\xc601|\xc77c|\xc774|\xc0bc|\xc0ac|\xc624|\xc721|\xce60|\xd314|\xad6c)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xc601" -> integer 0+        "\xc77c" -> integer 1+        "\xc774" -> integer 2+        "\xc0bc" -> integer 3+        "\xc0ac" -> integer 4+        "\xc624" -> integer 5+        "\xc721" -> integer 6+        "\xce60" -> integer 7+        "\xd314" -> integer 8+        "\xad6c" -> integer 9+        _ -> Nothing+      _ -> Nothing+  }++ruleIntegerType1PowersOfTen :: Rule+ruleIntegerType1PowersOfTen = Rule+  { name = "integer - TYPE 1: powers of ten"+  , pattern =+    [ regex "(\xc2ed|\xbc31|\xcc9c|\xb9cc|\xc5b5|\xc870)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xc2ed" -> double 10   >>= withGrain 1  >>= withMultipliable+        "\xbc31" -> double 1e2  >>= withGrain 2  >>= withMultipliable+        "\xcc9c" -> double 1e3  >>= withGrain 3  >>= withMultipliable+        "\xb9cc" -> double 1e4  >>= withGrain 4  >>= withMultipliable+        "\xc5b5" -> double 1e8  >>= withGrain 8  >>= withMultipliable+        "\xc870" -> double 1e12 >>= withGrain 12 >>= withMultipliable+        _ -> Nothing+      _ -> Nothing+  }++ruleSum :: Rule+ruleSum = Rule+  { name = "intersect 2 numbers"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleIntegerType2 :: Rule+ruleIntegerType2 = Rule+  { name = "integer (1..10) - TYPE 2"+  , pattern =+    [ regex "(\xd558\xb098|\xb458|\xc14b|\xb137|\xb2e4\xc12f|\xc5ec\xc12f|\xc77c\xacf1|\xc5ec\xb35f|\xc544\xd649)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xd558\xb098" -> integer 1+        "\xb458" -> integer 2+        "\xc14b" -> integer 3+        "\xb137" -> integer 4+        "\xb2e4\xc12f" -> integer 5+        "\xc5ec\xc12f" -> integer 6+        "\xc77c\xacf1" -> integer 7+        "\xc5ec\xb35f" -> integer 8+        "\xc544\xd649" -> integer 9+        _ -> Nothing+      _ -> Nothing+  }++ruleFraction :: Rule+ruleFraction = Rule+  { name = "fraction"+  , pattern =+    [ dimension Numeral+    , regex "\xbd84(\xc758|\xc5d0)"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v2 / v1+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number - 삼점사"+  , pattern =+    [ dimension Numeral+    , regex "(\xc810|\xca5c)((\xc601|\xc77c|\xc774|\xc0bc|\xc0ac|\xc624|\xc721|\xce60|\xd314|\xad6c)+)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token RegexMatch (GroupMatch (_:match:_)):+       _) -> do+        let getDigit '\xc601' = Just "0"+            getDigit '\xc77c' = Just "1"+            getDigit '\xc774' = Just "2"+            getDigit '\xc0bc' = Just "3"+            getDigit '\xc0ac' = Just "4"+            getDigit '\xc624' = Just "5"+            getDigit '\xc721' = Just "6"+            getDigit '\xce60' = Just "7"+            getDigit '\xd314' = Just "8"+            getDigit '\xad6c' = Just "9"+            getDigit _ = Nothing+        v2 <- parseDouble . Text.concat . mapMaybe getDigit $ Text.unpack match+        double $ v1 + decimalsToDouble v2+      _ -> Nothing+  }++ruleIntegerType3 :: Rule+ruleIntegerType3 = Rule+  { name = "integer (21..99) - TYPE 2"+  , 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+  }++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.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleFew+  , ruleFraction+  , ruleFraction2+  , ruleHalf+  , ruleInteger+  , ruleIntegerForOrdinals+  , ruleIntegerNumeric+  , ruleIntegerType1+  , ruleIntegerType1PowersOfTen+  , ruleSum+  , ruleMultiply+  , ruleIntegerType2+  , ruleIntegerType3+  , ruleIntegerTypeAndOrdinals+  , ruleIntegerWithThousandsSeparator+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithOr+  ]
+ Duckling/Numeral/MY/Corpus.hs view
@@ -0,0 +1,71 @@+-- 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.MY.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = MY}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "၀"+             , "သုံည"+             , "မရှိ"+             ]+  , examples (NumeralValue 1)+             [ "၁"+             , "တစ်"+             , "ပထမ"+             ]+  , examples (NumeralValue 2)+             [ "၂"+             , "နှစ်"+             , "ဒုတိယ"+             ]+  , examples (NumeralValue 3)+             [ "၃"+             , "သုံး"+             , "တတိယ"+             ]+  , examples (NumeralValue 30)+             [ "သုံးဆယ်"+             ]+  , examples (NumeralValue 33)+             [ "သုံးဆယ့်သုံး"+             ]+  , examples (NumeralValue 14)+             [ "ဆယ့်လေး"+             ]+  , examples (NumeralValue 17)+             [ "ဆယ့်ခုနှစ်"+             ]+  , examples (NumeralValue 200)+             [ "နှစ်ရာ"+             ]+  , examples (NumeralValue 900)+             [ "ကိုးရာ"+             ]+  , examples (NumeralValue 5000)+             [ "ငါးထောင်"+             ]+  , examples (NumeralValue 80000)+             [ "ရှစ်သောင်း"+             ]+  ]
+ Duckling/Numeral/MY/Rules.hs view
@@ -0,0 +1,181 @@+-- 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 #-}++module Duckling.Numeral.MY.Rules+  ( rules ) where++import Prelude+import Data.String++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++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer (11..99) "+  , pattern =+    [ numberBetween 1 10+    , regex "\x1006\x101a\x103a\x1037"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2 * 10+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (0..9) - numeric"+  , pattern =+    [ regex "(\x1040|\x1041|\x1042|\x1043|\x1044|\x1045|\x1046|\x1047|\x1048|\x1049)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x1040" -> integer 0+        "\x1041" -> integer 1+        "\x1042" -> integer 2+        "\x1043" -> integer 3+        "\x1044" -> integer 4+        "\x1045" -> integer 5+        "\x1046" -> integer 6+        "\x1047" -> integer 7+        "\x1048" -> integer 8+        "\x1049" -> integer 9+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer (11..19) "+  , pattern =+    [ regex "\x1006\x101a\x103a\x1037"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 10+      _ -> Nothing+  }++ruleIntegerPali :: Rule+ruleIntegerPali = Rule+  { name = "integer (1..3) - pali"+  , pattern =+    [ regex "(\x1015\x1011\x1019|\x1012\x102f\x1010\x102d\x101a|\x1010\x1010\x102d\x101a)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x1015\x1011\x1019" -> integer 1+        "\x1012\x102f\x1010\x102d\x101a" -> integer 2+        "\x1010\x1010\x102d\x101a" -> integer 3+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer (100..900)"+  , pattern =+    [ numberBetween 1 10+    , regex "\x101b\x102c"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 100+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer (1000..9000)"+  , pattern =+    [ numberBetween 1 10+    , regex "\x1011\x1031\x102c\x1004\x103a"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 1000+      _ -> Nothing+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer (10000..90000)"+  , pattern =+    [ numberBetween 1 10+    , regex "\x101e\x1031\x102c\x1004\x103a\x1038"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 10000+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "\x101e\x102f\x1036\x100a|\x1019\x101b\x103e\x102d"+    ]+  , prod = \_ -> integer 0+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer (10..90)"+  , pattern =+    [ numberBetween 1 10+    , regex "\x1006\x101a\x103a"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 10+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (1..10)"+  , pattern =+    [ regex "(\x1010\x1005\x103a|\x1014\x103e\x1005\x103a|\x101e\x102f\x1036\x1038|\x101c\x1031\x1038|\x1004\x102b\x1038|\x1001\x103c\x1031\x102b\x1000\x103a|\x1001\x102f\x1014\x103e\x1005\x103a|\x101b\x103e\x1005\x103a|\x1000\x102d\x102f\x1038|\x1010\x1005\x103a\x1006\x101a\x103a)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x1010\x1005\x103a" -> integer 1+        "\x1014\x103e\x1005\x103a" -> integer 2+        "\x101e\x102f\x1036\x1038" -> integer 3+        "\x101c\x1031\x1038" -> integer 4+        "\x1004\x102b\x1038" -> integer 5+        "\x1001\x103c\x1031\x102b\x1000\x103a" -> integer 6+        "\x1001\x102f\x1014\x103e\x1005\x103a" -> integer 7+        "\x101b\x103e\x1005\x103a" -> integer 8+        "\x1000\x102d\x102f\x1038" -> integer 9+        "\x1010\x1005\x103a\x1006\x101a\x103a" -> integer 10+        _ -> Nothing+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleIntegerNumeric+  , ruleIntegerPali+  ]
+ Duckling/Numeral/NB/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Numeral.NB.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NB}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "null"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "én"+             , "en"+             , "Ett"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "to"+             , "et par"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "syv"+             , "sju"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "fjorten"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "seksten"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "sytten"+             , "søtten"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "atten"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "tyve"+             , "Tjue"+             ]+  , examples (NumeralValue 30)+             [ "30"+             , "tretti"+             , "tredve"+             ]+  , examples (NumeralValue 70)+             [ "70"+             , "søtti"+             , "sytti"+             ]+  , 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"+             , "minus 1.200.000"+             , "negativ 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tusen"+             , "fem tusen"+             ]+  , examples (NumeralValue 100)+             [ "hundre"+             ]+  , examples (NumeralValue 5020)+             [ "fem tusen og tjue"+             ]+  ]
+ Duckling/Numeral/NB/Rules.hs view
@@ -0,0 +1,325 @@+-- 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 #-}++module Duckling.Numeral.NB.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "og"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus\\s?|negativ\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "(noen )?f\x00e5"+    ]+  , prod = \_ -> integer 3+  }++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 dot = Text.singleton '.'+                 comma = Text.singleton ','+                 fmt = Text.replace comma dot $ Text.replace dot Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "enkelt"+    ]+  , prod = \_ -> integer 1 >>= withGrain 1+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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\\$\x20ac]|$)"+    ]+  , 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+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(hundre(de)?|tusen?|million(er)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "hundre"    -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "hundrede"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tuse"      -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tusen"     -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "million"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "millioner" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++ruleAPair :: Rule+ruleAPair = Rule+  { name = "a pair"+  , pattern =+    [ regex "et par"+    ]+  , prod = \_ -> integer 2 >>= withGrain 1+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "dusin"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++zeroToNineteenMap :: HashMap Text Integer+zeroToNineteenMap = HashMap.fromList+  [ ( "null" , 0 )+  , ( "ingen" , 0 )+  , ( "intet" , 0 )+  , ( "en" , 1 )+  , ( "ett" , 1 )+  , ( "\x00e9n" , 1 )+  , ( "to" , 2 )+  , ( "tre" , 3 )+  , ( "fire" , 4 )+  , ( "fem" , 5 )+  , ( "seks" , 6 )+  , ( "sju" , 7 )+  , ( "syv" , 7 )+  , ( "otte" , 8 )+  , ( "ni" , 9 )+  , ( "ti" , 10 )+  , ( "elleve" , 11 )+  , ( "tolv" , 12 )+  , ( "tretten" , 13 )+  , ( "fjorten" , 14 )+  , ( "femten" , 15 )+  , ( "seksten" , 16 )+  , ( "s\x00f8tten" , 17 )+  , ( "sytten" , 17 )+  , ( "atten" , 18 )+  , ( "nitten" , 19 )+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(intet|ingen|null|en|ett|\x00e9n|to|tretten|tre|fire|femten|fem|seksten|seks|syv|sju|\x00e5tte|nitten|ni|ti|elleve|tolv|fjorten|sytten|s\x00f8tten|atten)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToNineteenMap >>= integer+      _ -> Nothing+  }++dozensMap :: HashMap Text Integer+dozensMap = HashMap.fromList+  [ ( "tyve" , 20 )+  , ( "tjue" , 20 )+  , ( "tredve" , 30 )+  , ( "tretti" , 30 )+  , ( "f\x00f8rti" , 40 )+  , ( "femti" , 50 )+  , ( "seksti" , 60 )+  , ( "sytti" , 70 )+  , ( "s\x00f8tti" , 70 )+  , ( "\x00e5tti" , 80 )+  , ( "nitti" , 90 )+  ]++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(tyve|tjue|tredve|tretti|f\x00f8rti|femti|seksti|sytti|s\x00f8tti|\x00e5tti|nitti)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) dozensMap >>= integer+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "komma"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton '.') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAPair+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleIntersectWithAnd+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSingle+  ]
+ Duckling/Numeral/NL/Corpus.hs view
@@ -0,0 +1,91 @@+-- 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.NL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nul"+             , "geen"+             , "niks"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "een"+             , "één"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "twee"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "3 en 30"+             , "drieendertig"+             , "drieëndertig"+             , "drie en dertig"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "veertien"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "zestien"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "zeventien"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "achtien"+             ]+  , 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 duizend"+             , "vijf duizend"+             ]+  , examples (NumeralValue 122)+             [ "honderd tweeëntwintig"+             , "honderd tweeentwintig"+             , "honderd twee en twintig"+             ]+  , examples (NumeralValue 20000)+             [ "twintig duizend"+             ]+  ]
+ Duckling/Numeral/NL/Rules.hs view
@@ -0,0 +1,289 @@+-- 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 #-}++module Duckling.Numeral.NL.Rules+  ( rules ) where++import Control.Monad (join)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|min|minus|negatief"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "meerdere"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "tien"+    ]+  , 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 dot = Text.singleton '.'+                 comma = Text.singleton ','+                 fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer ([2-9][1-9])"+  , pattern =+    [ regex "(een|twee|drie|vier|vijf|zes|zeven|acht|negen)(?:e|\x00eb)n(twintig|dertig|veertig|vijftig|zestig|zeventig|tachtig|negentig)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- HashMap.lookup (Text.toLower m1) zeroNineteenMap+        v2 <- HashMap.lookup (Text.toLower m2) dozenMap+        integer $ v1 + v2+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , dimension Numeral+    ]+  , 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\\$\x20ac]|$)"+    ]+  , 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+  }++ruleNumeralsEn :: Rule+ruleNumeralsEn = Rule+  { name = "numbers en"+  , pattern =+    [ numberBetween 1 10+    , regex "en"+    , oneOf [20, 30 .. 90]+    ]+  , 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 "(honderd|duizend|miljoen)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "honderd" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "duizend" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "miljoen" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _         -> Nothing+      _ -> Nothing+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple"+  , pattern =+    [ regex "(een )?paar"+    ]+  , prod = \_ -> integer 2+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "dozijn"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1+  }++zeroNineteenMap :: HashMap Text Integer+zeroNineteenMap = HashMap.fromList+  [ ("niks", 0)+  , ("nul", 0)+  , ("geen", 0)+  , ("\x00e9\x00e9n", 1)+  , ("een", 1)+  , ("twee", 2)+  , ("drie", 3)+  , ("vier", 4)+  , ("vijf", 5)+  , ("zes", 6)+  , ("zeven", 7)+  , ("acht", 8)+  , ("negen", 9)+  , ("tien", 10)+  , ("elf", 11)+  , ("twaalf", 12)+  , ("dertien", 13)+  , ("veertien", 14)+  , ("vijftien", 15)+  , ("zestien", 16)+  , ("zeventien", 17)+  , ("achtien", 18)+  , ("negentien", 19)+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(geen|nul|niks|een|\x00e9\x00e9n|twee|drie|vier|vijftien|vijf|zestien|zes|zeventien|zeven|achtien|acht|negentien|negen|tien|elf|twaalf|dertien|veertien)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroNineteenMap >>= integer+      _ -> Nothing+  }++dozenMap :: HashMap Text Integer+dozenMap = HashMap.fromList+  [ ("twintig", 20)+  , ("dertig", 30)+  , ("veertig", 40)+  , ("vijftig", 50)+  , ("zestig", 60)+  , ("zeventig", 70)+  , ("tachtig", 80)+  , ("negentig", 90)+  ]++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(twintig|dertig|veertig|vijftig|zestig|zeventig|tachtig|negentig)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) dozenMap >>= integer+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntersect+  , ruleMultiply+  , ruleNumeralsEn+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleTen+  ]
+ Duckling/Numeral/PL/Corpus.hs view
@@ -0,0 +1,125 @@+-- 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.PL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "nic"+             , "zero"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "jeden"+             , "pojedynczy"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "dwa"+             , "para"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "trzydzieści trzy"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "czternaście"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "szesnaście"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "siedemnaście"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "osiemnaście"+             ]+  , 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"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1,200,000"+             , "-1200000"+             , "minus 1,200,000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tysięcy"+             , "pięć tysięcy"+             ]+  , examples (NumeralValue 122)+             [ "sto dwadzieścia dwa"+             ]+  , examples (NumeralValue 200000)+             [ "dwieście tysięcy"+             ]+  , examples (NumeralValue 21011)+             [ "dwadzieścia jeden tysięcy i jedenaście"+             , "dwadzieścia jeden tysięcy jedenaście"+             ]+  , examples (NumeralValue 721012)+             [ "siedemset dwadzieścia jeden tysięcy dwanaście"+             , "siedemset dwadzieścia jeden tysięcy i dwanaście"+             ]+  , examples (NumeralValue 65000000)+             [ "sześćdziesiąt pięć milionów"+             ]+  , examples (NumeralValue 31256721)+             [ "trzydzieści jeden milionów dwieście pięćdziesiąt sześć tysięcy siedemset dwadzieścia jeden"+             ]+  , examples (NumeralValue 15)+             [ "piętnasta"+             ]+  ]
+ Duckling/Numeral/PL/Rules.hs view
@@ -0,0 +1,613 @@+-- 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 #-}++module Duckling.Numeral.PL.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleSixteen :: Rule+ruleSixteen = Rule+  { name = "sixteen"+  , pattern =+    [ regex "szesna(s|\x015b)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 16+  }++ruleFourteen :: Rule+ruleFourteen = Rule+  { name = "fourteen"+  , pattern =+    [ regex "czterna(s|\x015b)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 14+  }++ruleTwo :: Rule+ruleTwo = Rule+  { name = "two"+  , pattern =+    [ regex "dw(a|(o|\x00f3)(ch|m)|oma|iema|ie)"+    ]+  , prod = \_ -> integer 2+  }++ruleSixty :: Rule+ruleSixty = Rule+  { name = "sixty"+  , pattern =+    [ regex "sze(\x015b\x0107)dziesi(\x0105)t|sze(\x015b\x0107)dziesi(\x0119)ci(u|oma)"+    ]+  , prod = \_ -> integer 60+  }++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "i|a"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus\\s?|negative\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleOne :: Rule+ruleOne = Rule+  { name = "one"+  , pattern =+    [ regex "jed(en|nego|nemu|nym|nej|n(a|\x0105))"+    ]+  , prod = \_ -> integer 1+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "dzisi(e|\x0119)(\x0107|c)(iu|ioma)?"+    ]+  , prod = \_ -> integer 10+  }++ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo :: Rule+ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo = Rule+  { name = "special composition for missing hundreds like in one twenty two"+  , pattern =+    [ numberBetween 1 10+    , numberBetween 10 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double (v1 * 100 + v2)+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleNine :: Rule+ruleNine = Rule+  { name = "nine"+  , pattern =+    [ regex "dziewi(e|\x0119)(\x0107|c)(iu|ioma)?"+    ]+  , prod = \_ -> integer 9+  }++ruleNumeral8 :: Rule+ruleNumeral8 = Rule+  { name = "number 800"+  , pattern =+    [ regex "(osiem(set| setek))"+    ]+  , prod = \_ -> integer 800 >>= withGrain 2+  }++ruleTwelve :: Rule+ruleTwelve = Rule+  { name = "twelve"+  , pattern =+    [ regex "dwunast(u|oma)|dwana(\x015b|s)cie"+    ]+  , prod = \_ -> integer 12+  }++ruleDecimalNumeral :: Rule+ruleDecimalNumeral = Rule+  { name = "decimal number"+  , pattern =+    [ regex "(\\d*\\.\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> parseDecimal True match+      _ -> Nothing+  }++ruleFifteen :: Rule+ruleFifteen = Rule+  { name = "fifteen"+  , pattern =+    [ regex "pi(\x0119)tna(s|\x015b)(ta|tu|cie|toma)"+    ]+  , prod = \_ -> integer 15+  }++ruleEleven :: Rule+ruleEleven = Rule+  { name = "eleven"+  , pattern =+    [ regex "jedena(stu|(s|\x015b)cie|stoma)"+    ]+  , prod = \_ -> integer 11+  }++ruleThirteen :: Rule+ruleThirteen = Rule+  { name = "thirteen"+  , pattern =+    [ regex "trzyna(\x015b|s)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 13+  }++ruleThirty :: Rule+ruleThirty = Rule+  { name = "thirty"+  , pattern =+    [ regex "trzydzie(\x015b)ci|trzydziest(u|oma)"+    ]+  , prod = \_ -> integer 30+  }++ruleNumeral2 :: Rule+ruleNumeral2 = Rule+  { name = "number 200"+  , pattern =+    [ regex "dwie((\x015b)cie| setki)"+    ]+  , prod = \_ -> integer 200 >>= withGrain 2+  }++ruleSeventeen :: Rule+ruleSeventeen = Rule+  { name = "seventeen"+  , pattern =+    [ regex "siedemna(s|\x015b)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 17+  }++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number 100"+  , pattern =+    [ regex "(sto|setki)"+    ]+  , prod = \_ -> integer 100 >>= withGrain 2+  }++ruleNumeral9 :: Rule+ruleNumeral9 = Rule+  { name = "number 900"+  , pattern =+    [ regex "dziewi(\x0119\x0107)(set| setek)"+    ]+  , prod = \_ -> integer 900 >>= withGrain 2+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "pojedynczy"+    ]+  , prod = \_ -> integer 1+  }++ruleTwenty :: Rule+ruleTwenty = Rule+  { name = "twenty"+  , pattern =+    [ regex "dwadzie(\x015b|s)cia|dwudziest(u|oma)"+    ]+  , prod = \_ -> integer 20+  }++ruleAFew :: Rule+ruleAFew = Rule+  { name = "a few"+  , pattern =+    [ regex "kilk(a|u)"+    ]+  , prod = \_ -> integer 3+  }++ruleEight :: Rule+ruleEight = Rule+  { name = "eight"+  , pattern =+    [ regex "o(s|\x015b)(iem|miu|mioma)"+    ]+  , prod = \_ -> integer 8+  }++ruleNumeral5 :: Rule+ruleNumeral5 = Rule+  { name = "number 500"+  , pattern =+    [ regex "pi(\x0119\x0107)(set| setek)"+    ]+  , prod = \_ -> integer 500 >>= withGrain 2+  }++ruleNumeral3 :: Rule+ruleNumeral3 = Rule+  { name = "number 300"+  , pattern =+    [ regex "(trzy(sta| setki))"+    ]+  , prod = \_ -> integer 300 >>= withGrain 2+  }++ruleZero :: Rule+ruleZero = Rule+  { name = "zero"+  , pattern =+    [ regex "(zero|nic)"+    ]+  , prod = \_ -> integer 0+  }++ruleThousand :: Rule+ruleThousand = Rule+  { name = "thousand"+  , pattern =+    [ regex "ty(s|\x015b)i(a|\x0105|\x0119)c(e|y)?"+    ]+  , prod = \_ -> integer 1000 >>= withGrain 3 >>= withMultipliable+  }++ruleMillion :: Rule+ruleMillion = Rule+  { name = "million"+  , pattern =+    [ regex "milion(y|(\x00f3)w)?"+    ]+  , prod = \_ -> integer 1000000 >>= withGrain 6 >>= withMultipliable+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleThree :: Rule+ruleThree = Rule+  { name = "three"+  , pattern =+    [ regex "trz(y|ema|ech)"+    ]+  , prod = \_ -> integer 3+  }++ruleFour :: Rule+ruleFour = Rule+  { name = "four"+  , pattern =+    [ regex "czter(ej|y|ech|em|ema)"+    ]+  , prod = \_ -> integer 4+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++ruleNumeral7 :: Rule+ruleNumeral7 = Rule+  { name = "number 700"+  , pattern =+    [ regex "(siedem(set| setek))"+    ]+  , prod = \_ -> integer 700 >>= withGrain 2+  }++ruleAPair :: Rule+ruleAPair = Rule+  { name = "a pair"+  , pattern =+    [ regex "para?"+    ]+  , prod = \_ -> integer 2+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple"+  , pattern =+    [ regex "pare"+    ]+  , prod = \_ -> integer 2+  }++ruleSix :: Rule+ruleSix = Rule+  { name = "six"+  , pattern =+    [ regex "sze(s|\x015b)(c|\x0107)(iu|oma|u)?"+    ]+  , prod = \_ -> integer 6+  }++ruleNumeral6 :: Rule+ruleNumeral6 = Rule+  { name = "number 600"+  , pattern =+    [ regex "(sze\x015b\x0107(set| setek))"+    ]+  , prod = \_ -> integer 600 >>= withGrain 2+  }++ruleNumeral4 :: Rule+ruleNumeral4 = Rule+  { name = "number 400"+  , pattern =+    [ regex "(cztery(sta| setki))"+    ]+  , prod = \_ -> integer 400 >>= withGrain 2+  }++ruleFive :: Rule+ruleFive = Rule+  { name = "five"+  , pattern =+    [ regex "pi(e|\x0119)(c|\x0107)(iu|oma|u)?"+    ]+  , prod = \_ -> integer 5+  }++ruleFourty :: Rule+ruleFourty = Rule+  { name = "fou?rty"+  , pattern =+    [ regex "czterdzie(\x015b)ci|czterdziest(u|oma)"+    ]+  , prod = \_ -> integer 40+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "tuzin"+    ]+  , prod = \_ -> integer 12 >>= withMultipliable+  }++ruleSeven :: Rule+ruleSeven = Rule+  { name = "seven"+  , pattern =+    [ regex "sied(miu|em|mioma)"+    ]+  , prod = \_ -> integer 7+  }++ruleNineteen :: Rule+ruleNineteen = Rule+  { name = "nineteen"+  , pattern =+    [ regex "dziewietna(s|\x015b)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 19+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 21..99"+  , 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+  }++ruleEighteen :: Rule+ruleEighteen = Rule+  { name = "eighteen"+  , pattern =+    [ regex "osiemna(s|\x015b)(tu|cie|toma)"+    ]+  , prod = \_ -> integer 18+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "dot|point"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleFifty :: Rule+ruleFifty = Rule+  { name = "fifty"+  , pattern =+    [ regex "pi(\x0119\x0107)dziesi(\x0105)t|pi(\x0119\x0107)dziesi(\x0119)ci(u|oma)"+    ]+  , prod = \_ -> integer 50+  }++rules :: [Rule]+rules =+  [ ruleAFew+  , ruleAPair+  , ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleEight+  , ruleEighteen+  , ruleEleven+  , ruleFifteen+  , ruleFifty+  , ruleFive+  , ruleFour+  , ruleFourteen+  , ruleFourty+  , ruleInteger2+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleIntersectWithAnd+  , ruleMillion+  , ruleMultiply+  , ruleNine+  , ruleNineteen+  , ruleNumeral+  , ruleNumeral2+  , ruleNumeral3+  , ruleNumeral4+  , ruleNumeral5+  , ruleNumeral6+  , ruleNumeral7+  , ruleNumeral8+  , ruleNumeral9+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , ruleOne+  , ruleSeven+  , ruleSeventeen+  , ruleSingle+  , ruleSix+  , ruleSixteen+  , ruleSixty+  , ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo+  , ruleTen+  , ruleThirteen+  , ruleThirty+  , ruleThousand+  , ruleThree+  , ruleTwelve+  , ruleTwenty+  , ruleTwo+  , ruleZero+  ]
+ Duckling/Numeral/PT/Corpus.hs view
@@ -0,0 +1,166 @@+-- 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.PT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 1)+             [ "1"+             , "um"+             , "Uma"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "dois"+             , "duas"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "três"+             , "tres"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "seis"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "onze"+             ]+  , examples (NumeralValue 12)+             [ "12"+             , "doze"+             , "uma dúzia"+             , "uma duzia"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "Catorze"+             , "quatorze"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "dezesseis"+             , "dezasseis"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "dezessete"+             , "dezassete"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "dezoito"+             ]+  , examples (NumeralValue 19)+             [ "19"+             , "dezenove"+             , "dezanove"+             ]+  , examples (NumeralValue 21)+             [ "21"+             , "vinte e um"+             ]+  , examples (NumeralValue 23)+             [ "23"+             , "vinte e tres"+             , "vinte e três"+             ]+  , examples (NumeralValue 24)+             [ "24"+             , "vinte e quatro"+             , "duas dúzias"+             , "duas duzias"+             ]+  , examples (NumeralValue 50)+             [ "50"+             , "cinquenta"+             , "cinqüenta"+             , "cincoenta"+             ]+  , examples (NumeralValue 70)+             [ "setenta"+             ]+  , examples (NumeralValue 78)+             [ "setenta e oito"+             ]+  , examples (NumeralValue 80)+             [ "oitenta"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "trinta e três"+             , "trinta e tres"+             ]+  , 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 100)+             [ "100"+             , "Cem"+             ]+  , examples (NumeralValue 243)+             [ "243"+             ]+  , examples (NumeralValue 300)+             [ "trezentos"+             ]+  , 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 ponto cinco"+             , "um ponto cinco"+             , "1,5"+             ]+  ]
+ Duckling/Numeral/PT/Rules.hs view
@@ -0,0 +1,306 @@+-- 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 #-}++module Duckling.Numeral.PT.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|menos"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> 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 dot = Text.singleton '.'+                 comma = Text.singleton ','+                 fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleNumeral2 :: Rule+ruleNumeral2 = Rule+  { name = "number (20..90)"+  , pattern =+    [ regex "(vinte|trinta|quarenta|cincoenta|cinq(\x00fc)enta|cinquenta|sessenta|setenta|oitenta|noventa)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "vinte" -> integer 20+        "trinta" -> integer 30+        "quarenta" -> integer 40+        "cinq\252enta" -> integer 50+        "cincoenta" -> integer 50+        "cinquenta" -> integer 50+        "sessenta" -> integer 60+        "setenta" -> integer 70+        "oitenta" -> integer 80+        "noventa" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "number (0..15)"+  , pattern =+    [ regex "(zero|uma?|d(oi|ua)s|tr(\x00ea|e)s|quatro|cinco|seis|sete|oito|nove|dez|onze|doze|treze|(ca|qua)torze|quinze)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "zero" -> integer 0+        "uma" -> integer 1+        "um" -> integer 1+        "dois" -> integer 2+        "duas" -> integer 2+        "tr\x00eas" -> integer 3+        "tres" -> integer 3+        "quatro" -> integer 4+        "cinco" -> integer 5+        "seis" -> integer 6+        "sete" -> integer 7+        "oito" -> integer 8+        "nove" -> integer 9+        "dez" -> integer 10+        "onze" -> integer 11+        "doze" -> integer 12+        "treze" -> integer 13+        "catorze" -> integer 14+        "quatorze" -> integer 14+        "quinze" -> integer 15+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral5 :: Rule+ruleNumeral5 = Rule+  { name = "number (16..19)"+  , pattern =+    [ regex "(dez[ea]sseis|dez[ea]ssete|dezoito|dez[ea]nove)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "dezesseis" -> integer 16+        "dezasseis" -> integer 16+        "dezessete" -> integer 17+        "dezassete" -> integer 17+        "dezoito" -> integer 18+        "dezenove" -> integer 19+        "dezanove" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral3 :: Rule+ruleNumeral3 = Rule+  { name = "number (16..19)"+  , pattern =+    [ numberWith TNumeral.value (== 10)+    , regex "e"+    , numberBetween 6 10+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ 10 + v+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++ruleNumeral6 :: Rule+ruleNumeral6 = Rule+  { name = "number 100..1000 "+  , pattern =+    [ regex "(ce(m|to)|duzentos|trezentos|quatrocentos|quinhentos|seiscentos|setecentos|oitocentos|novecentos|mil)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "cento" -> integer 100+        "cem" -> integer 100+        "duzentos" -> integer 200+        "trezentos" -> integer 300+        "quatrocentos" -> integer 400+        "quinhentos" -> integer 500+        "seiscentos" -> integer 600+        "setecentos" -> integer 700+        "oitocentos" -> integer 800+        "novecentos" -> integer 900+        "mil" -> integer 1000+        _ -> Nothing+      _ -> Nothing+  }++ruleNumeral4 :: Rule+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 "e"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       _:+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "d(\x00fa|u)zias?"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++ruleNumeralDozen :: Rule+ruleNumeralDozen = Rule+  { name = "number dozen"+  , pattern =+    [ numberBetween 1 11+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2, TNumeral.grain = Just g}):+       _) -> double (v1 * v2) >>= withGrain g+      _ -> Nothing+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 200..999"+  , pattern =+    [ 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 $ v1 * 100 + v2+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "ponto"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace (Text.singleton '.') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeral2+  , ruleNumeral3+  , ruleNumeral4+  , ruleNumeral5+  , ruleNumeral6+  , ruleNumeralDotNumeral+  , ruleNumeralDozen+  , ruleNumerals+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/RO/Corpus.hs view
@@ -0,0 +1,192 @@+-- 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.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "zero"+             , "nici unul"+             , "nici unu"+             , "nici una"+             , "nici o"+             , "nicio"+             , "nimic"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "unu"+             , "unul"+             , "un"+             , "o"+             , "intai"+             , "întâi"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "doi"+             , "doua"+             , "două"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "trei"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "patru"+             ]+  , examples (NumeralValue 5)+             [ "5"+             , "cinci"+             ]+  , examples (NumeralValue 6)+             [ "6"+             , "sase"+             , "șase"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "sapte"+             , "șapte"+             ]+  , examples (NumeralValue 8)+             [ "8"+             , "opt"+             ]+  , examples (NumeralValue 9)+             [ "9"+             , "noua"+             , "nouă"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "zece"+             , "zeci"+             ]+  , examples (NumeralValue 10)+             [ "10"+             , "zece"+             ]+  , examples (NumeralValue 11)+             [ "11"+             , "unsprezece"+             , "unspe"+             , "unșpe"+             ]+  , examples (NumeralValue 19)+             [ "19"+             , "nouasprezece"+             , "nouaspe"+             , "nouăsprezece"+             , "nouășpe"+             ]+  , examples (NumeralValue 70)+             [ "70"+             , "sapte zeci"+             , "șapte zeci"+             ]+  , 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 3000000)+             [ "3000000"+             , "3.000.000"+             ]+  , examples (NumeralValue 1200000)+             [ "1.200.000"+             , "1200000"+             ]+  , examples (NumeralValue (-1200000))+             [ "-1.200.000"+             , "-1200000"+             , "minus 1.200.000"+             ]+  , examples (NumeralValue (-3))+             [ "-3"+             , "3 negativ"+             ]+  , examples (NumeralValue 5000)+             [ "5 mii"+             , "cinci mii"+             ]+  , examples (NumeralValue 1000)+             [ "o mie"+             , "1 mie"+             ]+  , examples (NumeralValue 100)+             [ "o suta"+             , "o sută"+             , "1 suta"+             , "1 sută"+             ]+  , examples (NumeralValue 300)+             [ "3 sute"+             , "trei sute"+             ]+  , examples (NumeralValue 1000000)+             [ "un milion"+             , "1 milion"+             ]+  , examples (NumeralValue 7000000)+             [ "7 milioane"+             , "sapte milioane"+             , "șapte milioane"+             ]+  , examples (NumeralValue 1000000000)+             [ "un miliard"+             , "1 miliard"+             ]+  , examples (NumeralValue 9000000000)+             [ "9 miliarde"+             , "noua miliarde"+             , "nouă miliarde"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "douazeci"+             , "doua zeci"+             , "douăzeci"+             , "două zeci"+             ]+  , examples (NumeralValue 23)+             [ "23"+             , "20 3"+             , "douazeci 3"+             , "douăzeci 3"+             , "douăzeci trei"+             , "douazeci si trei"+             , "douăzeci și trei"+             ]+  ]
+ Duckling/Numeral/RO/Rules.hs view
@@ -0,0 +1,316 @@+-- 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 #-}++module Duckling.Numeral.RO.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleNumeralsPrefixWithOrMinus :: Rule+ruleNumeralsPrefixWithOrMinus = Rule+  { name = "numbers prefix with - or minus"+  , pattern =+    [ regex "-|minus\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> Nothing+  }++ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo :: Rule+ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo = Rule+  { name = "special composition for missing hundreds like in one twenty two"+  , pattern =+    [ numberBetween 1 10+    , numberBetween 11 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = hundreds}):+       Token Numeral (NumeralData {TNumeral.value = rest}):+       _) -> double $ hundreds * 100 + rest+      _ -> 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 dot = Text.singleton '.'+                 comma = Text.singleton ','+                 fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , dimension Numeral+    ]+  , 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+  }++ruleIntersectCuI :: Rule+ruleIntersectCuI = Rule+  { name = "intersect (cu și)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "(s|\x0219)i"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleNumeralsSuffixesWithNegativ :: Rule+ruleNumeralsSuffixesWithNegativ = Rule+  { name = "numbers suffixes with (negativ)"+  , pattern =+    [ dimension Numeral+    , regex "(negativ|neg)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ v * (-1)+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(sut(a|e|\x0103)?|milio(n|ane)?|miliar(de?)?|mi[ei]?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "suta"      -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "sute"      -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "sut\x0103" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "mi"        -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "mie"       -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "mii"       -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "milio"     -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milion"    -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "milioane"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "miliar"    -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "miliard"   -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "miliarde"  -> double 1e9 >>= withGrain 9 >>= withMultipliable+        _           -> Nothing+      _ -> Nothing+  }++zeroTenMap :: HashMap Text Integer+zeroTenMap = HashMap.fromList+  [ ("zero", 0)+  , ("nimic", 0)+  , ("nicio", 0)+  , ("nici o", 0)+  , ("nici una", 0)+  , ("nici unu", 0)+  , ("nici unul", 0)+  , ("un", 1)+  , ("una", 1)+  , ("unu", 1)+  , ("unul", 1)+  , ("intai", 1)+  , ("\x00eentai", 1)+  , ("int\x00e2i", 1)+  , ("\x00eent\x00e2i", 1)+  , ("o", 1)+  , ("doi", 2)+  , ("doua", 2)+  , ("dou\x0103", 2)+  , ("trei", 3)+  , ("patru", 4)+  , ("cinci", 5)+  , ("sase", 6)+  , ("\537ase", 6)+  , ("sapte", 7)+  , ("\537apte", 7)+  , ("opt", 8)+  , ("noua", 9)+  , ("nou\x0103", 9)+  , ("zece", 10)+  , ("zeci", 10)+  ]++ruleIntegerZeroTen :: Rule+ruleIntegerZeroTen = Rule+  { name = "integer (0..10)"+  , pattern =+    [ regex "(zero|nimic|nici(\\s?o|\\sun(a|ul?))|una|unul?|doi|dou(a|\x0103)|trei|patru|cinci|(s|\x0219)ase|(s|\x0219)apte|opt|nou(a|\x0103)|zec[ei]|(i|\x00ee)nt(a|\x00e2)i|un|o)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroTenMap >>= integer+      _ -> Nothing+  }++elevenNineteenMap :: HashMap Text Integer+elevenNineteenMap = HashMap.fromList+  [ ("un", 11)+  , ("doi", 12)+  , ("trei", 13)+  , ("pai", 14)+  , ("cin", 15)+  , ("cinci", 15)+  , ("sai", 16)+  , ("\537ai", 16)+  , ("sapti", 17)+  , ("\537apti", 17)+  , ("sapte", 17)+  , ("\537apte", 17)+  , ("opti", 18)+  , ("opt", 18)+  , ("noua", 19)+  , ("nou\x0103", 19)+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (11..19)"+  , pattern =+    [ regex "(cin|sapti|opti)(s|\x0219)pe|(cinci|(s|\x0219)apte|opt)sprezece|(un|doi|trei|pai|(s|\x0219)ai|nou(a|\x0103))((s|\x0219)pe|sprezece)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (e1:_:e2:_:r:_)):_) -> do+        match <- case () of+          _ | not $ Text.null e1 -> Just e1+            | not $ Text.null e2 -> Just e2+            | not $ Text.null r  -> Just r+            | otherwise          -> Nothing+        HashMap.lookup (Text.toLower match) elevenNineteenMap >>= integer+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(dou(a|\x0103)|trei|patru|cinci|(s|\x0219)ai|(s|\x0219)apte|opt|nou(a|\x0103))\\s?zeci"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        unit <- HashMap.lookup (Text.toLower match) zeroTenMap+        integer (unit * 10) >>= withGrain 2 >>= withMultipliable+      _ -> Nothing+  }++ruleIntegerCuSeparatorDeMiiDot :: Rule+ruleIntegerCuSeparatorDeMiiDot = Rule+  { name = "integer cu separator de mii dot"+  , pattern =+    [ regex "(\\d{1,3}(\\.\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace (Text.singleton '.') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleIntegerZeroTen+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerCuSeparatorDeMiiDot+  , ruleIntegerNumeric+  , ruleIntersect+  , ruleIntersectCuI+  , ruleMultiply+  , ruleNumeralsPrefixWithOrMinus+  , ruleNumeralsSuffixesWithNegativ+  , rulePowersOfTen+  , ruleSpecialCompositionForMissingHundredsLikeInOneTwentyTwo+  ]
+ Duckling/Numeral/RU/Corpus.hs view
@@ -0,0 +1,114 @@+-- 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.RU.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RU}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "ноль"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "один"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "02"+             , "два"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "три"+             , "03"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "четыре"+             , "04"+             ]+  , examples (NumeralValue 5)+             [ "пять"+             , "5"+             , "05"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "тридцать три"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "четырнадцать"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "шестнадцать"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "семнадцать"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "восемнадцать"+             ]+  , examples (NumeralValue 525)+             [ "пятьсот двадцать пять"+             , "525"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 точка 1"+             , "один точка один"+             ]+  , examples (NumeralValue 0.77)+             [ "0.77"+             , ".77"+             ]+  , examples (NumeralValue 100000)+             [ "100000"+             , "100к"+             , "100К"+             ]+  , examples (NumeralValue 3000000)+             [ "3М"+             , "3000К"+             , "3000000"+             ]+  , examples (NumeralValue 1200000)+             [ "1200000"+             , "1.2М"+             , "1200К"+             , ".0012Г"+             ]+  , examples (NumeralValue (-1200000))+             [ "-1200000"+             , "минус 1200000"+             , "-1.2М"+             , "-1200К"+             , "-.0012Г"+             ]+  ]
+ Duckling/Numeral/RU/Rules.hs view
@@ -0,0 +1,279 @@+-- 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 #-}++module Duckling.Numeral.RU.Rules+  ( rules ) where++import qualified Data.HashMap.Strict as HashMap+import Data.HashMap.Strict (HashMap)+import Data.Maybe+import qualified Data.Text as Text+import Data.Text (Text)+import Prelude+import Data.String++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++dozensMap :: HashMap Text Integer+dozensMap = HashMap.fromList+  [ ( "\x0434\x0432\x0430\x0434\x0446\x0430\x0442\x044c", 20)+  , ( "\x0442\x0440\x0438\x0434\x0446\x0430\x0442\x044c", 30)+  , ( "\x0441\x043e\x0440\x043e\x043a", 40)+  , ( "\x043f\x044f\x0442\x044c\x0434\x0435\x0441\x044f\x0442", 50)+  , ( "\x0448\x0435\x0441\x0442\x044c\x0434\x0435\x0441\x044f\x0442", 60)+  , ( "\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442", 70)+  , ( "\x0432\x043e\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442", 80)+  , ( "\x0434\x0435\x0432\x044f\x043d\x043e\x0441\x0442\x043e", 90)+  ]++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(\x0434\x0432\x0430\x0434\x0446\x0430\x0442\x044c|\x0442\x0440\x0438\x0434\x0446\x0430\x0442\x044c|\x0441\x043e\x0440\x043e\x043a|\x043f\x044f\x0442\x044c\x0434\x0435\x0441\x044f\x0442|\x0448\x0435\x0441\x0442\x044c\x0434\x0435\x0441\x044f\x0442|\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442|\x0432\x043e\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442|\x0434\x0435\x0432\x044f\x043d\x043e\x0441\x0442\x043e)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) dozensMap >>= integer+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- toInteger <$> parseInt match+        integer v+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 2"+  , pattern =+    [ regex "(\x0434\x0432\x0430|\x0434\x0432\x0435|\x0434\x0432\x043e\x0435|\x043f\x0430\x0440\x0430|\x043f\x0430\x0440\x0443|\x043f\x0430\x0440\x043e\x0447\x043a\x0443|\x043f\x0430\x0440\x043e\x0447\x043a\x0430)"+    ]+  , prod = \_ -> integer 2+  }++hundredsMap :: HashMap Text Integer+hundredsMap = HashMap.fromList+  [ ( "\x0441\x0442\x043e", 100)+  , ( "\x0434\x0432\x0435\x0441\x0442\x0438", 200)+  , ( "\x0442\x0440\x0438\x0441\x0442\x043e", 300)+  , ( "\x0447\x0435\x0442\x044b\x0440\x0435\x0441\x0442\x043e", 400)+  , ( "\x043f\x044f\x0442\x044c\x0441\x043e\x0442", 500)+  , ( "\x0448\x0435\x0441\x0442\x044c\x0441\x043e\x0442", 600)+  , ( "\x0441\x0435\x043c\x044c\x0441\x043e\x0442", 700)+  , ( "\x0432\x043e\x0441\x0435\x043c\x044c\x0441\x043e\x0442", 800)+  , ( "\x0434\x0435\x0432\x044f\x0442\x044c\x0441\x043e\x0442", 900)+  ]++ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer (100..900)"+  , pattern =+    [ regex "(\x0441\x0442\x043e|\x0434\x0432\x0435\x0441\x0442\x0438|\x0442\x0440\x0438\x0441\x0442\x043e|\x0447\x0435\x0442\x044b\x0440\x0435\x0441\x0442\x043e|\x043f\x044f\x0442\x044c\x0441\x043e\x0442|\x0448\x0435\x0441\x0442\x044c\x0441\x043e\x0442|\x0441\x0435\x043c\x044c\x0441\x043e\x0442|\x0432\x043e\x0441\x0435\x043c\x044c\x0441\x043e\x0442|\x0434\x0435\x0432\x044f\x0442\x044c\x0441\x043e\x0442)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredsMap >>= integer+      _ -> Nothing+  }++ruleNumeralsPrefixWithMinus :: Rule+ruleNumeralsPrefixWithMinus = Rule+  { name = "numbers prefix with -, minus"+  , pattern =+    [ regex "-|\x043c\x0438\x043d\x0443\x0441\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "((\x043a|\x043c|\x0433)|(\x041a|\x041c|\x0413))(?=[\\W\\$\x20ac]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "\x043a" -> double $ v * 1e3+         "\x041a" -> double $ v * 1e3+         "\x043c" -> double $ v * 1e6+         "\x041c" -> double $ v * 1e6+         "\x0433" -> double $ v * 1e9+         "\x0413" -> double $ v * 1e9+         _   -> Nothing+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 101..999"+  , pattern =+    [ oneOf [300, 600, 500, 100, 800, 200, 900, 700, 400]+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "(\x043d\x043e\x043b\x044c)"+    ]+  , prod = \_ -> integer 0+  }++threeToNineteenMap:: HashMap Text Integer+threeToNineteenMap = HashMap.fromList+  [ ( "\x0442\x0440\x0438", 3)+  , ( "\x0447\x0435\x0442\x044b\x0440\x0435", 4)+  , ( "\x043f\x044f\x0442\x044c", 5)+  , ( "\x0448\x0435\x0441\x0442\x044c", 6)+  , ( "\x0441\x0435\x043c\x044c", 7)+  , ( "\x0432\x043e\x0441\x0435\x043c\x044c", 8)+  , ( "\x0434\x0435\x0432\x044f\x0442\x044c", 9)+  , ( "\x0434\x0435\x0441\x044f\x0442\x044c", 10)+  , ( "\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 11)+  , ( "\x0434\x0432\x0435\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 12)+  , ( "\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 13)+  , ( "\x0447\x0435\x0442\x044b\x0440\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 14)+  , ( "\x043f\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 15)+  , ( "\x0448\x0435\x0441\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 16)+  , ( "\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 17)+  , ( "\x0432\x043e\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 18)+  , ( "\x0434\x0435\x0432\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c", 19)+  ]++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer (3..19)"+  , pattern =+    [ regex "(\x0442\x0440\x0438|\x0447\x0435\x0442\x044b\x0440\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0447\x0435\x0442\x044b\x0440\x0435|\x043f\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x043f\x044f\x0442\x044c|\x0448\x0435\x0441\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0448\x0435\x0441\x0442\x044c|\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0441\x0435\x043c\x044c|\x0432\x043e\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0432\x043e\x0441\x0435\x043c\x044c|\x0434\x0435\x0432\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0434\x0435\x0432\x044f\x0442\x044c|\x0434\x0435\x0441\x044f\x0442\x044c|\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0434\x0432\x0435\x043d\x0430\x0434\x0446\x0430\x0442\x044c|\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x0430\x0442\x044c)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) threeToNineteenMap >>= integer+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 1"+  , pattern =+    [ regex "(\x043e\x0434\x0438\x043d|\x043e\x0434\x043d\x0430|\x043e\x0434\x043d\x0443)"+    ]+  , prod = \_ -> integer 1+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "\x0442\x043e\x0447\x043a\x0430"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/SV/Corpus.hs view
@@ -0,0 +1,106 @@+-- 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.SV.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = SV}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "noll"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "en"+             , "ett"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "två"+             , "ett par"+             ]+  , examples (NumeralValue 7)+             [ "7"+             , "sju"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "Fjorton"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "sexton"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "sjutton"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "arton"+             ]+  , examples (NumeralValue 20)+             [ "20"+             , "tjugo"+             ]+  , 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"+             , "minus 1.200.000"+             , "negativ 1200000"+             , "-1,2M"+             , "-1200K"+             , "-,0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 tusen"+             , "fem tusen"+             ]+  ]
+ Duckling/Numeral/SV/Rules.hs view
@@ -0,0 +1,323 @@+-- 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 #-}++module Duckling.Numeral.SV.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "och"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|minus\\s?|negativ\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Numeral (NumeralData {TNumeral.value = v}):+       _) -> double $ v * (-1)+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         v <- parseInt match+         integer $ toInteger v+      _ -> Nothing+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "(n\x00e5gra )?f\x00e5"+    ]+  , prod = \_ -> integer 3+  }++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 dot = Text.singleton '.'+            comma = Text.singleton ','+            fmt = Text.replace comma dot $ Text.replace dot 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+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleSingle :: Rule+ruleSingle = Rule+  { name = "single"+  , pattern =+    [ regex "enkel"+    ]+  , prod = \_ -> integer 1 >>= withGrain 1+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(hundra?|tusen?|miljon(er)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "hundr"    -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "hundra"   -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tuse"     -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tusen"    -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "miljon"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "miljoner" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _          -> Nothing+      _ -> Nothing+  }++ruleCouple :: Rule+ruleCouple = Rule+  { name = "couple, a pair"+  , pattern =+    [ regex "ett par"+    ]+  , prod = \_ -> integer 2+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "dussin"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++zeroToNineteenMap :: HashMap Text Integer+zeroToNineteenMap = HashMap.fromList+  [ ( "inget"    , 0 )+  , ( "ingen"    , 0 )+  , ( "noll"     , 0 )+  , ( "en"       , 1 )+  , ( "ett"      , 1 )+  , ( "tv\x00e5" , 2 )+  , ( "tre"      , 3 )+  , ( "fyra"     , 4 )+  , ( "fem"      , 5 )+  , ( "sex"      , 6 )+  , ( "sju"      , 7 )+  , ( "\x00e5tta", 8 )+  , ( "nio"      , 9 )+  , ( "tio"      , 10 )+  , ( "elva"     , 11 )+  , ( "tolv"     , 12 )+  , ( "tretton"  , 13 )+  , ( "fjorton"  , 14 )+  , ( "femton"   , 15 )+  , ( "sexton"   , 16 )+  , ( "sjutton"  , 17 )+  , ( "arton"    , 18 )+  , ( "nitton"   , 19 )+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(inget|ingen|noll|en|ett|tv\x00e5|tretton|tre|fyra|femton|fem|sexton|sex|sjutton|sju|\x00e5tta|nio|tio|elva|tolv|fjorton|arton|nitton)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) zeroToNineteenMap >>= integer+      _ -> Nothing+  }++dozenMap :: HashMap Text Integer+dozenMap = HashMap.fromList+  [ ( "tjugo"      , 20)+  , ( "trettio"    , 30)+  , ( "fyrtio"     , 40)+  , ( "femtio"     , 50)+  , ( "sextio"     , 60)+  , ( "sjuttio"    , 70)+  , ( "\x00e5ttio" , 80)+  , ( "nittio"     , 90)+  ]++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(tjugo|trettio|fyrtio|femtio|sextio|sjuttio|\x00e5ttio|nittio)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) dozenMap >>= integer+      _ -> Nothing+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "komma"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace (Text.singleton '.') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCouple+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleIntersectWithAnd+  , ruleMultiply+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleSingle+  ]
+ Duckling/Numeral/TR/Corpus.hs view
@@ -0,0 +1,180 @@+-- 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.TR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = TR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "yok"+             , "hiç"+             , "sıfır"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "bir"+             , "tek"+             , "yek"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "iki"+             , "çift"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "otuzüç"+             , "otuz üç"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "ondört"+             , "on dört"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "onaltı"+             , "on altı"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "onyedi"+             , "on yedi"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "onsekiz"+             , "on sekiz"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "bir virgül bir"+             , "bir nokta bir"+             ]+  , examples (NumeralValue 0.77)+             [ "0.77"+             , ".77"+             ]+  , examples (NumeralValue 100000)+             [ "100,000"+             , "100000"+             , "100K"+             , "100k"+             , "100b"+             ]+  , examples (NumeralValue 3000000)+             [ "3M"+             , "3000K"+             , "3000000"+             , "3,000,000"+             ]+  , examples (NumeralValue 1200000)+             [ "1,200,000"+             , "1200000"+             , "1.2M"+             , "1200K"+             , ".0012G"+             , "1200B"+             ]+  , examples (NumeralValue (-1200000))+             [ "- 1,200,000"+             , "-1200000"+             , "eksi 1,200,000"+             , "negatif 1200000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             , "-1200B"+             ]+  , examples (NumeralValue 5000)+             [ "5 bin"+             , "beş bin"+             ]+  , examples (NumeralValue 50)+             [ "5 deste"+             , "beş deste"+             ]+  , examples (NumeralValue 200000)+             [ "iki yüz bin"+             , "ikiyüzbin"+             ]+  , examples (NumeralValue 21011)+             [ "yirmi bir bin on bir"+             , "yirmibir bin onbir"+             ]+  , examples (NumeralValue 721012)+             [ "yedi yüz yirmibir bin on iki"+             , "yedi yüz yirmi bir bin on iki"+             , "yediyüz yirmibir bin oniki"+             ]+  , examples (NumeralValue 300341)+             [ "üçyüzbin üçyüz kırkbir"+             , "üç yüz bin üç yüz kırk bir"+             ]+  , examples (NumeralValue 40348)+             [ "kırkbin üçyüz kırksekiz"+             , "kırk bin üç yüz kırk sekiz"+             ]+  , examples (NumeralValue 31256721)+             [ "otuz bir milyon iki yüz elli altı bin yedi yüz yirmi bir"+             ]+  , examples (NumeralValue 107)+             [ "107"+             , "yüz yedi"+             ]+  , examples (NumeralValue 5.5)+             [ "beş buçuk"+             , "beşbuçuk"+             , "5 buçuk"+             , "5.5"+             ]+  , examples (NumeralValue 3500000)+             [ "3.5 milyon"+             , "3500000"+             , "üç buçuk milyon"+             , "üçbuçuk milyon"+             , "3.5M"+             ]+  , examples (NumeralValue 0.5)+             [ "yarım"+             , "0.5"+             ]+  , examples (NumeralValue 2500)+             [ "2.5 bin"+             , "2500"+             , "iki buçuk bin"+             , "ikibuçuk bin"+             ]+  , examples (NumeralValue 2200000)+             [ "2.2 milyon"+             , "iki nokta iki milyon"+             ]+  , examples (NumeralValue 72.5)+             [ "yetmişikibuçuk"+             , "yetmişiki buçuk"+             , "72.5"+             ]+  ]
+ Duckling/Numeral/TR/Rules.hs view
@@ -0,0 +1,733 @@+-- 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 #-}++module Duckling.Numeral.TR.Rules+  ( rules ) where++import qualified Data.HashMap.Strict as HashMap+import Data.HashMap.Strict (HashMap)+import Data.Maybe+import qualified Data.Text as Text+import Data.Text (Text)+import Prelude+import Data.String++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++hundredsMap :: HashMap Text Integer+hundredsMap = HashMap.fromList+  [ ( "y\x00fcz", 100)+  , ( "ikiy\x00fcz", 200)+  , ( "\x00fc\x00e7y\x00fcz", 300)+  , ( "d\x00f6rty\x00fcz", 400)+  , ( "be\x015fy\x00fcz", 500)+  , ( "alt\x0131y\x00fcz", 600)+  , ( "yediy\x00fcz", 700)+  , ( "sekizy\x00fcz", 800)+  , ( "dokuzy\x00fcz", 900)+  ]+++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer 100..900"+  , pattern =+    [ regex "(y\x00fcz|ikiy\x00fcz|\x00fc\x00e7y\x00fcz|d\x00f6rty\x00fcz|be\x015fy\x00fcz|alt\x0131y\x00fcz|yediy\x00fcz|sekizy\x00fcz|dokuzy\x00fcz)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredsMap >>= integer >>= withGrain 2+      _ -> Nothing+  }++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|eksi\\s?|negatif\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        double (v * (- 1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleACoupleOf :: Rule+ruleACoupleOf = Rule+  { name = "a couple (of)"+  , pattern =+    [ regex "(bir )?\x00e7ift"+    ]+  , prod = \_ -> integer 2 >>= withGrain 1+  }++ruleFew :: Rule+ruleFew = Rule+  { name = "few"+  , pattern =+    [ regex "(bir)?az"+    ]+  , prod = \_ -> integer 3+  }++ruleTen :: Rule+ruleTen = Rule+  { name = "ten"+  , pattern =+    [ regex "on"+    ]+  , prod = \_ -> integer 10 >>= withGrain 1 >>= withMultipliable+  }++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.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++ruleMultiply :: Rule+ruleMultiply = Rule+  { name = "compose by multiplication"+  , pattern =+    [ dimension Numeral+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = val1}):+       Token Numeral (NumeralData {TNumeral.value = val2, TNumeral.grain = g2}):+       _) | isNothing g2 || (isJust g2 && val2 > val1) -> case g2 of+         Nothing -> double $ val1 * val2+         Just g  -> double (val1 * val2) >>= withGrain g+      _ -> 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+  }++numeralSuffixesHalfsuffixTextMap :: HashMap Text Double+numeralSuffixesHalfsuffixTextMap = HashMap.fromList+  [ ( "birbu\x00e7uk", 1.5)+  , ( "bibu\x00e7uk", 1.5)+  , ( "ikibu\x00e7uk", 2.5)+  , ( "\x00fc\231bu\x00e7uk", 3.5)+  , ( "d\x00f6rtbu\x00e7uk", 4.5)+  , ( "be\351bu\x00e7uk", 5.5)+  , ( "alt\x0131bu\x00e7uk", 6.5)+  , ( "yedibu\x00e7uk", 7.5)+  , ( "sekizbu\x00e7uk", 8.5)+  , ( "dokuzbu\x00e7uk", 9.5)+  ]++ruleNumeralSuffixesHalfsuffixText :: Rule+ruleNumeralSuffixesHalfsuffixText = Rule+  { name = "number suffixes (half-suffix text) (1..9)"+  , pattern =+    [ regex "((bir?|iki|\x00fc\x00e7|d\x00f6rt|be\x015f|alt\x0131|yedi|sekiz|dokuz)(bu\x00e7uk))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) numeralSuffixesHalfsuffixTextMap >>= double+      _ -> Nothing+  }++tenToNintynineMap :: HashMap Text Integer+tenToNintynineMap = HashMap.fromList+  [ ( "onbi", 11)+  , ( "onbir", 11)+  , ( "oniki", 12)+  , ( "on\x00fc\x00e7", 13)+  , ( "ond\x00f6rt", 14)+  , ( "onbe\x015f", 15)+  , ( "onalt\x0131", 16)+  , ( "onyedi", 17)+  , ( "onsekiz", 18)+  , ( "ondokuz", 19)+  , ( "yirmibi", 21)+  , ( "yirmibir", 21)+  , ( "yirmiiki", 22)+  , ( "yirmi\x00fc\x00e7", 23)+  , ( "yirmid\x00f6rt", 24)+  , ( "yirmibe\x015f", 25)+  , ( "yirmialt\x0131", 26)+  , ( "yirmiyedi", 27)+  , ( "yirmisekiz", 28)+  , ( "yirmidokuz", 29)+  , ( "otuzbi", 31)+  , ( "otuzbir", 31)+  , ( "otuziki", 32)+  , ( "otuz\x00fc\x00e7", 33)+  , ( "otuzd\x00f6rt", 34)+  , ( "otuzbe\x015f", 35)+  , ( "otuzalt\x0131", 36)+  , ( "otuzyedi", 37)+  , ( "otuzsekiz", 38)+  , ( "otuzdokuz", 39)+  , ( "k\x0131rkbir", 41)+  , ( "k\x0131rkbi", 41)+  , ( "k\x0131rkiki", 42)+  , ( "k\x0131rk\x00fc\x00e7", 43)+  , ( "k\x0131rkd\x00f6rt", 44)+  , ( "k\x0131rkbe\x015f", 45)+  , ( "k\x0131rkalt\x0131", 46)+  , ( "k\x0131rkyedi", 47)+  , ( "k\x0131rksekiz", 48)+  , ( "k\x0131rkdokuz", 49)+  , ( "ellibi", 51)+  , ( "ellibir", 51)+  , ( "elliiki", 52)+  , ( "elli\x00fc\x00e7", 53)+  , ( "ellid\x00f6rt", 54)+  , ( "ellibe\x015f", 55)+  , ( "ellialt\x0131", 56)+  , ( "elliyedi", 57)+  , ( "ellisekiz", 58)+  , ( "ellidokuz", 59)+  , ( "altm\x0131\x015fbir", 61)+  , ( "atm\x0131\x015fbir", 61)+  , ( "atm\x0131\x015fiki", 62)+  , ( "altm\x0131\x015fiki", 62)+  , ( "atm\x0131\x015f\x00fc\x00e7", 63)+  , ( "altm\x0131\x015f\x00fc\x00e7", 63)+  , ( "atm\x0131\x015fd\x00f6rt", 64)+  , ( "altm\x0131\x015fd\x00f6rt", 64)+  , ( "atm\x0131\x015fbe\x015f", 65)+  , ( "altm\x0131\x015fbe\x015f", 65)+  , ( "atm\x0131\x015falt\x0131", 66)+  , ( "altm\x0131\x015falt\x0131", 66)+  , ( "altm\x0131\x015fyedi", 67)+  , ( "atm\x0131\x015fyedi", 67)+  , ( "altm\x0131\x015fsekiz", 68)+  , ( "atm\x0131\x015fsekiz", 68)+  , ( "atm\x0131\x015fdokuz", 69)+  , ( "altm\x0131\x015fdokuz", 69)+  , ( "yetmi\x015fbir", 71)+  , ( "yetmi\x015fbi", 71)+  , ( "yetmi\x015fiki", 72)+  , ( "yetmi\x015f\x00fc\x00e7", 73)+  , ( "yetmi\x015fd\x00f6rt", 74)+  , ( "yetmi\x015fbe\x015f", 75)+  , ( "yetmi\x015falt\x0131", 76)+  , ( "yetmi\x015fyedi", 77)+  , ( "yetmi\x015fsekiz", 78)+  , ( "yetmi\x015fdokuz", 79)+  , ( "seksenbir", 81)+  , ( "seksenbi", 81)+  , ( "sekseniki", 82)+  , ( "seksen\x00fc\x00e7", 83)+  , ( "seksend\x00f6rt", 84)+  , ( "seksenbe\x015f", 85)+  , ( "seksenalt\x0131", 86)+  , ( "seksenyedi", 87)+  , ( "seksensekiz", 88)+  , ( "seksendokuz", 89)+  , ( "doksanbi", 91)+  , ( "doksanbir", 91)+  , ( "doksaniki", 92)+  , ( "doksan\x00fc\x00e7", 93)+  , ( "doksand\x00f6rt", 94)+  , ( "doksanbe\x015f", 95)+  , ( "doksanalt\x0131", 96)+  , ( "doksanyedi", 97)+  , ( "doksansekiz", 98)+  , ( "doksandokuz", 99)+  ]++ruleInteger3 :: Rule+ruleInteger3 = 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\x0131rk|elli|atm\x0131\x015f|altm\x0131\x015f|yetmi\x015f|seksen|doksan)(bir|bi|iki|\x00fc\x00e7|d\x00f6rt|be\x015f|alt\x0131|yedi|sekiz|dokuz))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tenToNintynineMap >>= integer+      _ -> Nothing+  }+++thousandsMap :: HashMap Text Integer+thousandsMap = HashMap.fromList+  [ ( "bin", 1000)+  , ( "ikibin", 2000)+  , ( "\x00fc\x00e7bin", 3000)+  , ( "d\x00f6rtbin", 4000)+  , ( "be\x015fbin", 5000)+  , ( "alt\x0131bin", 6000)+  , ( "yedibin", 7000)+  , ( "sekizbin", 8000)+  , ( "dokuzbin", 9000)+  ]++ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer 1000..9000"+  , pattern =+    [ regex "(bin|ikibin|\x00fc\x00e7bin|d\x00f6rtbin|be\x015fbin|alt\x0131bin|yedibin|sekizbin|dokuzbin)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) thousandsMap >>= integer >>= withGrain 3+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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 "([kmgb])(?=[\\W\\$\x20ac]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+          "k" -> double $ v * 1e3+          "b" -> double $ v * 1e3+          "m" -> double $ v * 1e6+          "g" -> double $ v * 1e9+          _ -> Nothing+      _ -> Nothing+  }++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(y(\x00fc)z|bin|milyon)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "y\x00fcz" -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "bin"      -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "milyon"   -> double 1e6 >>= withGrain 6 >>= withMultipliable+        _          -> Nothing+      _ -> Nothing+  }++tenThousandsMap :: HashMap Text Integer+tenThousandsMap = HashMap.fromList+  [  ( "onbin", 10000)+   , ( "yirmibin", 20000)+   , ( "otuzbin", 30000)+   , ( "k\x0131rkbin", 40000)+   , ( "ellibin", 50000)+   , ( "altm\x0131\x015fbin", 60000)+   , ( "atm\x0131\x015fbin", 60000)+   , ( "yetmi\x015fbin", 70000)+   , ( "seksenbin", 80000)+   , ( "doksanbin", 90000)+  ]++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer 10000..90000"+  , pattern =+    [ regex "(onbin|yirmibin|otuzbin|k\x0131rkbin|ellibin|atm\x0131\x015fbin|altm\x0131\x015fbin|yetmi\x015fbin|seksenbin|doksanbin)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tenThousandsMap >>= integer >>= withGrain 4+      _ -> Nothing+  }++hundredThousandsMap :: HashMap Text Integer+hundredThousandsMap = HashMap.fromList+  [ ( "y\x00fczbin", 100000)+  , ( "ikiy\x00fczbin", 200000)+  , ( "\x00fc\x00e7y\x00fczbin", 300000)+  , ( "d\x00f6rty\x00fczbin", 400000)+  , ( "be\x015fy\x00fczbin", 500000)+  , ( "alt\x0131y\x00fczbin", 600000)+  , ( "yediy\x00fczbin", 700000)+  , ( "sekizy\x00fczbin", 800000)+  , ( "dokuzy\x00fczbin", 900000)+  ]++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 100000..900000"+  , pattern =+    [ regex "(y\x00fczbin|ikiy\x00fczbin|\x00fc\x00e7y\x00fczbin|d\x00f6rty\x00fczbin|be\x015fy\x00fczbin|alt\x0131y\x00fczbin|yediy\x00fczbin|sekizy\x00fczbin|dokuzy\x00fczbin)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredThousandsMap >>= integer >>= withGrain 5+      _ -> Nothing+  }++ruleHalf :: Rule+ruleHalf = Rule+  { name = "half"+  , pattern =+    [ regex "(yar\x0131m)"+    ]+  , prod = \_ -> double 0.5+  }++integer9Map :: HashMap Text Double+integer9Map = HashMap.fromList+  [ ( "onbirbu\x00e7uk", 11.5)+  , ( "onbibu\x00e7uk", 11.5)+  , ( "onikibu\x00e7uk", 12.5)+  , ( "on\x00fc\x00e7bu\x00e7uk", 13.5)+  , ( "ond\x00f6rtbu\x00e7uk", 14.5)+  , ( "onbe\x015fbu\x00e7uk", 15.5)+  , ( "onalt\x0131bu\x00e7uk", 16.5)+  , ( "onyedibu\x00e7uk", 17.5)+  , ( "onsekizbu\x00e7uk", 18.5)+  , ( "ondokuzbu\x00e7uk", 19.5)+  , ( "yirmibibu\x00e7uk", 21.5)+  , ( "yirmibirbu\x00e7uk", 21.5)+  , ( "yirmiikibu\x00e7uk", 22.5)+  , ( "yirmi\x00fc\x00e7bu\x00e7uk", 23.5)+  , ( "yirmid\x00f6rtbu\x00e7uk", 24.5)+  , ( "yirmibe\x015fbu\x00e7uk", 25.5)+  , ( "yirmialt\x0131bu\x00e7uk", 26.5)+  , ( "yirmiyedibu\x00e7uk", 27.5)+  , ( "yirmisekizbu\x00e7uk", 28.5)+  , ( "yirmidokuzbu\x00e7uk", 29.5)+  , ( "otuzbibu\x00e7uk", 31.5)+  , ( "otuzbirbu\x00e7uk", 31.5)+  , ( "otuzikibu\x00e7uk", 32.5)+  , ( "otuz\x00fc\x00e7bu\x00e7uk", 33.5)+  , ( "otuzd\x00f6rtbu\x00e7uk", 34.5)+  , ( "otuzbe\x015fbu\x00e7uk", 35.5)+  , ( "otuzalt\x0131bu\x00e7uk", 36.5)+  , ( "otuzyedibu\x00e7uk", 37.5)+  , ( "otuzsekizbu\x00e7uk", 38.5)+  , ( "otuzdokuzbu\x00e7uk", 39.5)+  , ( "k\x0131rkbirbu\x00e7uk", 41.5)+  , ( "k\x0131rkbibu\x00e7uk", 41.5)+  , ( "k\x0131rkikibu\x00e7uk", 42.5)+  , ( "k\x0131rk\x00fc\x00e7bu\x00e7uk", 43.5)+  , ( "k\x0131rkd\x00f6rtbu\x00e7uk", 44.5)+  , ( "k\x0131rkbe\x015fbu\x00e7uk", 45.5)+  , ( "k\x0131rkalt\x0131bu\x00e7uk", 46.5)+  , ( "k\x0131rkyedibu\x00e7uk", 47.5)+  , ( "k\x0131rksekizbu\x00e7uk", 48.5)+  , ( "k\x0131rkdokuzbu\x00e7uk", 49.5)+  , ( "ellibibu\x00e7uk", 51.5)+  , ( "ellibirbu\x00e7uk", 51.5)+  , ( "elliikibu\x00e7uk", 52.5)+  , ( "elli\x00fc\x00e7bu\x00e7uk", 53.5)+  , ( "ellid\x00f6rtbu\x00e7uk", 54.5)+  , ( "ellibe\x015fbu\x00e7uk", 55.5)+  , ( "ellialt\x0131bu\x00e7uk", 56.5)+  , ( "elliyedibu\x00e7uk", 57.5)+  , ( "ellisekizbu\x00e7uk", 58.5)+  , ( "ellidokuzbu\x00e7uk", 59.5)+  , ( "altm\x0131\x015fbirbu\x00e7uk", 61.5)+  , ( "atm\x0131\x015fbirbu\x00e7uk", 61.5)+  , ( "altm\x0131\x015fikibu\x00e7uk", 62.5)+  , ( "atm\x0131\x015fikibu\x00e7uk", 62.5)+  , ( "atm\x0131\x015f\x00fc\x00e7bu\x00e7uk", 63.5)+  , ( "altm\x0131\x015f\x00fc\x00e7bu\x00e7uk", 63.5)+  , ( "altm\x0131\x015fd\x00f6rtbu\x00e7uk", 64.5)+  , ( "atm\x0131\x015fd\x00f6rtbu\x00e7uk", 64.5)+  , ( "altm\x0131\x015fbe\x015fbu\x00e7uk", 65.5)+  , ( "atm\x0131\x015fbe\x015fbu\x00e7uk", 65.5)+  , ( "altm\x0131\x015falt\x0131bu\x00e7uk", 66.5)+  , ( "atm\x0131\x015falt\x0131bu\x00e7uk", 66.5)+  , ( "atm\x0131\x015fyedibu\x00e7uk", 67.5)+  , ( "altm\x0131\x015fyedibu\x00e7uk", 67.5)+  , ( "altm\x0131\x015fsekizbu\x00e7uk", 68.5)+  , ( "atm\x0131\x015fsekizbu\x00e7uk", 68.5)+  , ( "altm\x0131\x015fdokuzbu\x00e7uk", 69.5)+  , ( "atm\x0131\x015fdokuzbu\x00e7uk", 69.5)+  , ( "yetmi\x015fbibu\x00e7uk", 71.5)+  , ( "yetmi\x015fbirbu\x00e7uk", 71.5)+  , ( "yetmi\x015fikibu\x00e7uk", 72.5)+  , ( "yetmi\x015f\x00fc\x00e7bu\x00e7uk", 73.5)+  , ( "yetmi\x015fd\x00f6rtbu\x00e7uk", 74.5)+  , ( "yetmi\x015fbe\x015fbu\x00e7uk", 75.5)+  , ( "yetmi\x015falt\x0131bu\x00e7uk", 76.5)+  , ( "yetmi\x015fyedibu\x00e7uk", 77.5)+  , ( "yetmi\x015fsekizbu\x00e7uk", 78.5)+  , ( "yetmi\x015fdokuzbu\x00e7uk", 79.5)+  , ( "seksenbibu\x00e7uk", 81.5)+  , ( "seksenbirbu\x00e7uk", 81.5)+  , ( "seksenikibu\x00e7uk", 82.5)+  , ( "seksen\x00fc\x00e7bu\x00e7uk", 83.5)+  , ( "seksend\x00f6rtbu\x00e7uk", 84.5)+  , ( "seksenbe\x015fbu\x00e7uk", 85.5)+  , ( "seksenalt\x0131bu\x00e7uk", 86.5)+  , ( "seksenyedibu\x00e7uk", 87.5)+  , ( "seksensekizbu\x00e7uk", 88.5)+  , ( "seksendokuzbu\x00e7uk", 89.5)+  , ( "doksanbirbu\x00e7uk", 91.5)+  , ( "doksanbibu\x00e7uk", 91.5)+  , ( "doksanikibu\x00e7uk", 92.5)+  , ( "doksan\x00fc\x00e7bu\x00e7uk", 93.5)+  , ( "doksand\x00f6rtbu\x00e7uk", 94.5)+  , ( "doksanbe\x015fbu\x00e7uk", 95.5)+  , ( "doksanalt\x0131bu\x00e7uk", 96.5)+  , ( "doksanyedibu\x00e7uk", 97.5)+  , ( "doksansekizbu\x00e7uk", 98.5)+  , ( "doksandokuzbu\x00e7uk", 99.5)+  ]++ruleInteger9 :: Rule+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\x0131rk|elli|atm\x0131\x015f|altm\x0131\x015f|yetmi\x015f|seksen|doksan)(bir|bi|iki|\x00fc\x00e7|d\x00f6rt|be\x015f|alt\x0131|yedi|sekiz|dokuz)(bu\x00e7uk))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) integer9Map >>= double+      _ -> Nothing+  }++ruleDozen :: Rule+ruleDozen = Rule+  { name = "dozen"+  , pattern =+    [ regex "d\x00fczine"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++oneToNineMap :: HashMap Text Integer+oneToNineMap = HashMap.fromList+  [ ( "s\305f\305r", 0)+  , ( "yok", 0)+  , ( "hi\x00e7", 0)+  , ( "bir", 1)+  , ( "bi", 1)+  , ( "yek", 1)+  , ( "tek", 1)+  , ( "iki", 2)+  , ( "\x00fc\x00e7", 3)+  , ( "d\x00f6rt", 4)+  , ( "be\x015f", 5)+  , ( "alt\x0131", 6)+  , ( "yedi", 7)+  , ( "sekiz", 8)+  , ( "dokuz", 9)+  ]++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..9)"+  , pattern =+    [ regex "(yok|hi(\x00e7)|s(\x0131)f(\x0131)r|bir?|[ty]ek|iki|(\x00fc)(\x00e7)|d(\x00f6)rt|be(\x015f)|alt(\x0131)|yedi|sekiz|dokuz)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) oneToNineMap >>= integer+      _ -> Nothing+  }++numeralSuffixesHalfsuffixText2Map :: HashMap Text Double+numeralSuffixesHalfsuffixText2Map = HashMap.fromList+  [ ( "onbu\x00e7uk", 10.5)+  , ( "yirmibu\x00e7uk", 20.5)+  , ( "otuzbu\x00e7uk", 30.5)+  , ( "k\x0131rkbu\x00e7uk", 40.5)+  , ( "ellibu\x00e7uk", 50.5)+  , ( "atm\x0131\x015fbu\x00e7uk", 60.5)+  , ( "altm\x0131\x015fbu\x00e7uk", 60.5)+  , ( "yetmi\x015fbu\x00e7uk", 70.5)+  , ( "seksenbu\x00e7uk", 80.5)+  , ( "doksanbu\x00e7uk", 90.5)+  ]++ruleNumeralSuffixesHalfsuffixText2 :: Rule+ruleNumeralSuffixesHalfsuffixText2 = Rule+  { name = "number suffixes (half-suffix text) (10..90)"+  , pattern =+    [ regex "((on|yirmi|otuz|k\x0131rk|elli|atm\x0131\x015f|altm\x0131\x015f|yetmi\x015f|seksen|doksan)(bu\x00e7uk))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) numeralSuffixesHalfsuffixText2Map+        >>= double+      _ -> Nothing+  }++ruleNumeralSuffixesHalfSuffix :: Rule+ruleNumeralSuffixesHalfSuffix = Rule+  { name = "number suffixes (half-suffix)"+  , pattern =+    [ dimension Numeral+    , regex "(bu\x00e7uk)(?=[\\W\\$\x20ac]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 0.5+      _ -> Nothing+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 11..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 10, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleGroupOfTens :: Rule+ruleGroupOfTens = Rule+  { name = "group of ten(s)"+  , pattern =+    [ regex "deste"+    ]+  , prod = \_ -> integer 10 >>= withGrain 1 >>= withMultipliable+  }++tensMap :: HashMap Text Integer+tensMap = HashMap.fromList+  [ ( "on", 10)+  , ( "yirmi", 20)+  , ( "otuz", 30)+  , ( "k\x0131rk", 40)+  , ( "elli", 50)+  , ( "altm\x0131\x015f", 60)+  , ( "atm\x0131\x015f", 60)+  , ( "yetmi\x015f", 70)+  , ( "seksen", 80)+  , ( "doksan", 90)+  ]++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (10..90)"+  , pattern =+    [ regex "(on|yirmi|otuz|k\x0131rk|elli|atm\x0131\x015f|altm\x0131\x015f|yetmi\x015f|seksen|doksan)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) tensMap >>= integer+      _ -> Nothing+  }++ruleQuarter :: Rule+ruleQuarter = Rule+  { name = "quarter"+  , pattern =+    [ regex "(\x00e7eyrek)"+    ]+  , prod = \_ -> double 0.25+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "nokta|virg\x00fcl"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 ,"+  , pattern =+    [ regex "(\\d{1,3}(,\\d\\d\\d){1,5})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') Text.empty match) >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleACoupleOf+  , ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleDozen+  , ruleFew+  , ruleGroupOfTens+  , ruleHalf+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleInteger9+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleNumeralDotNumeral+  , ruleNumeralSuffixesHalfSuffix+  , ruleNumeralSuffixesHalfsuffixText+  , ruleNumeralSuffixesHalfsuffixText2+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleQuarter+  , ruleTen+  , ruleMultiply+  ]
+ Duckling/Numeral/Types.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Numeral.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Maybe+import Data.Text (Text)+import GHC.Generics+import Prelude++import Duckling.Resolve++data NumeralData = NumeralData+  { value        :: Double+  , grain        :: Maybe Int+  , multipliable :: Bool+  }+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve NumeralData where+  type ResolvedValue NumeralData = NumeralValue+  resolve _ NumeralData {value} = Just NumeralValue {vValue = value}++newtype NumeralValue = NumeralValue { vValue :: Double }+  deriving (Eq, Show)++instance ToJSON NumeralValue where+  toJSON (NumeralValue value) = object+    [ "type" .= ("value" :: Text)+    , "value" .= value+    ]++getIntValue :: Double -> Maybe Int+getIntValue x = if rest == 0 then Just int else Nothing+  where+    (int, rest) = properFraction x :: (Int, Double)++isInteger :: Double -> Bool+isInteger = isJust . getIntValue++isNatural :: Double -> Bool+isNatural x = isInteger x && x > 0++isIntegerBetween :: Double -> Int -> Int -> Bool+isIntegerBetween x low high = case getIntValue x of+  Just int -> low <= int && int <= high+  Nothing -> False
+ Duckling/Numeral/UK/Corpus.hs view
@@ -0,0 +1,114 @@+-- 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.UK.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = UK}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "нуль"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "один"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "02"+             , "два"+             ]+  , examples (NumeralValue 3)+             [ "3"+             , "три"+             , "03"+             ]+  , examples (NumeralValue 4)+             [ "4"+             , "чотири"+             , "04"+             ]+  , examples (NumeralValue 5)+             [ "п‘ять"+             , "5"+             , "05"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "тридцять три"+             , "0033"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "чотирнадцять"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "шістнадцять"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "сімнадцять"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "вісімнадцять"+             ]+  , examples (NumeralValue 525)+             [ "п‘ятсот двадцять п‘ять"+             , "525"+             ]+  , examples (NumeralValue 1.1)+             [ "1.1"+             , "1.10"+             , "01.10"+             , "1 крапка 1"+             , "один крапка один"+             ]+  , examples (NumeralValue 0.77)+             [ "0.77"+             , ".77"+             ]+  , examples (NumeralValue 100000)+             [ "100000"+             , "100к"+             , "100К"+             ]+  , examples (NumeralValue 3000000)+             [ "3М"+             , "3000К"+             , "3000000"+             ]+  , examples (NumeralValue 1200000)+             [ "1200000"+             , "1.2М"+             , "1200К"+             , ".0012Г"+             ]+  , examples (NumeralValue (-1200000))+             [ "-1200000"+             , "мінус 1200000"+             , "-1.2М"+             , "-1200К"+             , "-.0012Г"+             ]+  ]
+ Duckling/Numeral/UK/Rules.hs view
@@ -0,0 +1,278 @@+-- 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 #-}++module Duckling.Numeral.UK.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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++twentyNinetyMap :: HashMap Text Integer+twentyNinetyMap = HashMap.fromList+  [ ( "\x0434\x0432\x0430\x0434\x0446\x044f\x0442\x044c"             , 20 )+  , ( "\x0442\x0440\x0438\x0434\x0446\x044f\x0442\x044c"             , 30 )+  , ( "\x0441\x043e\x0440\x043e\x043a"                               , 40 )+  , ( "\x043f\x2018\x044f\x0442\x0434\x0435\x0441\x044f\x0442"       , 50 )+  , ( "\x0448\x0456\x0441\x0442\x0434\x0435\x0441\x044f\x0442"       , 60 )+  , ( "\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442"             , 70 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x043d\x043e\x0441\x0442\x043e" , 90 )+  , ( "\x0432\x0456\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442" , 80 )+  ]++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(\x0434\x0432\x0430\x0434\x0446\x044f\x0442\x044c|\x0442\x0440\x0438\x0434\x0446\x044f\x0442\x044c|\x0441\x043e\x0440\x043e\x043a|\x043f\x2018\x044f\x0442\x0434\x0435\x0441\x044f\x0442|\x0448\x0456\x0441\x0442\x0434\x0435\x0441\x044f\x0442|\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442|\x0432\x0456\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442|\x0434\x0435\x0432\x2018\x044f\x043d\x043e\x0441\x0442\x043e)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) twentyNinetyMap >>= integer+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 2"+  , pattern =+    [ regex "(\x0434\x0432\x0430|\x0434\x0432\x0456|\x0434\x0432\x043e\x0454|\x043f\x0430\x0440\x0430|\x043f\x0430\x0440\x0443|\x043f\x0430\x0440\x043e\x0447\x043a\x0443|\x043f\x0430\x0440\x043e\x0447\x043a\x0430)"+    ]+  , prod = \_ -> integer 2+  }++hundredsMap :: HashMap Text Integer+hundredsMap = HashMap.fromList+  [ ( "\x0441\x0442\x043e"                                     , 100 )+  , ( "\x0434\x0432\x0456\x0441\x0442\x0456"                   , 200 )+  , ( "\x0442\x0440\x0438\x0441\x0442\x0430"                   , 300 )+  , ( "\x0447\x043e\x0442\x0438\x0440\x0438\x0441\x0442\x0430" , 400 )+  , ( "\x043f\x2018\x044f\x0442\x0441\x043e\x0442"             , 500 )+  , ( "\x0448\x0456\x0441\x0442\x0441\x043e\x0442"             , 600 )+  , ( "\x0441\x0456\x043c\x0441\x043e\x0442"                   , 700 )+  , ( "\x0432\x0456\x0441\x0456\x043c\x0441\x043e\x0442"       , 800 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x0442\x0441\x043e\x0442" , 900 )+  ]+ruleInteger6 :: Rule+ruleInteger6 = Rule+  { name = "integer (100..900)"+  , pattern =+    [ regex "(\x0441\x0442\x043e|\x0434\x0432\x0456\x0441\x0442\x0456|\x0442\x0440\x0438\x0441\x0442\x0430|\x0447\x043e\x0442\x0438\x0440\x0438\x0441\x0442\x0430|\x043f\x2018\x044f\x0442\x0441\x043e\x0442|\x0448\x0456\x0441\x0442\x0441\x043e\x0442|\x0441\x0456\x043c\x0441\x043e\x0442|\x0432\x0456\x0441\x0456\x043c\x0441\x043e\x0442|\x0434\x0435\x0432\x2018\x044f\x0442\x0441\x043e\x0442)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) hundredsMap >>= integer+      _ -> Nothing+  }++ruleNumeralsPrefixWithMinus :: Rule+ruleNumeralsPrefixWithMinus = Rule+  { name = "numbers prefix with -, minus"+  , pattern =+    [ regex "-|\x043c\x0456\x043d\x0443\x0441\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "((\x043a|\x043c|\x0433)|(\x041a|\x041c|\x0413))(?=[\\W\\$\x20ac]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "\x043a" -> double $ v * 1e3+         "\x041a" -> double $ v * 1e3+         "\x043c" -> double $ v * 1e6+         "\x041c" -> double $ v * 1e6+         "\x0433" -> double $ v * 1e9+         "\x0413" -> double $ v * 1e9+         _   -> Nothing+      _ -> Nothing+  }++ruleInteger7 :: Rule+ruleInteger7 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger8 :: Rule+ruleInteger8 = Rule+  { name = "integer 101..999"+  , pattern =+    [ oneOf [300, 600, 500, 100, 800, 200, 900, 700, 400]+    , numberBetween 1 100+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer 0"+  , pattern =+    [ regex "(\x043d\x0443\x043b\x044c)"+    ]+  , prod = \_ -> integer 0+  }++threeNineteenMap :: HashMap Text Integer+threeNineteenMap = HashMap.fromList+  [ ( "\x0442\x0440\x0438"                                           , 3 )+  , ( "\x0447\x043e\x0442\x0438\x0440\x0438"                         , 4 )+  , ( "\x043f\x2018\x044f\x0442\x044c"                               , 5 )+  , ( "\x0448\x0456\x0441\x0442\x044c"                               , 6 )+  , ( "\x0441\x0456\x043c"                                           , 7 )+  , ( "\x0432\x0456\x0441\x0456\x043c"                               , 8 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x0442\x044c"                   , 9 )+  , ( "\x0434\x0435\x0441\x044f\x0442\x044c"                         , 10 )+  , ( "\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 11 )+  , ( "\x0434\x0432\x0430\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 12 )+  , ( "\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 13 )+  , ( "\x0447\x043e\x0442\x0438\x0440\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 14 )+  , ( "\x043f\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c"       , 15 )+  , ( "\x0448\x0456\x0441\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c"       , 16 )+  , ( "\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442\x044c"             , 17 )+  , ( "\x0432\x0456\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 18 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c" , 19 )+  ]+ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer (3..19)"+  , pattern =+    [ regex "(\x0442\x0440\x0438|\x0447\x043e\x0442\x0438\x0440\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0447\x043e\x0442\x0438\x0440\x0438|\x043f\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x043f\x2018\x044f\x0442\x044c|\x0448\x0456\x0441\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0448\x0456\x0441\x0442\x044c|\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0441\x0456\x043c|\x0432\x0456\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0432\x0456\x0441\x0456\x043c|\x0434\x0435\x0432\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0434\x0435\x0432\x2018\x044f\x0442\x044c|\x0434\x0435\x0441\x044f\x0442\x044c|\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0434\x0432\x0430\x043d\x0430\x0434\x0446\x044f\x0442\x044c|\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x044f\x0442\x044c)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup (Text.toLower match) threeNineteenMap >>= integer+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer 1"+  , pattern =+    [ regex "(\x043e\x0434\x0438\x043d|\x043e\x0434\x043d\x0430|\x043e\x0434\x043d\x0443|\x043e\x0434\x043d\x0435|\x043e\x0434\x043d\x043e\x0433\x043e)"+    ]+  , prod = \_ -> integer 1+  }++ruleNumeralDotNumeral :: Rule+ruleNumeralDotNumeral = Rule+  { name = "number dot number"+  , pattern =+    [ dimension Numeral+    , regex "\x043a\x0440\x0430\x043f\x043a\x0430"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (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 = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       _) -> let fmt = Text.replace (Text.singleton ',') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleInteger6+  , ruleInteger7+  , ruleInteger8+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeralDotNumeral+  , ruleNumeralsPrefixWithMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Numeral/VI/Corpus.hs view
@@ -0,0 +1,111 @@+-- 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.VI.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = VI}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "không"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "một"+             ]+  , examples (NumeralValue 2)+             [ "2"+             , "hai"+             ]+  , examples (NumeralValue 33)+             [ "33"+             , "ba mươi ba"+             ]+  , examples (NumeralValue 14)+             [ "14"+             , "mười bốn"+             ]+  , examples (NumeralValue 16)+             [ "16"+             , "mười sáu"+             ]+  , examples (NumeralValue 17)+             [ "17"+             , "mười bảy"+             ]+  , examples (NumeralValue 18)+             [ "18"+             , "mười tám"+             ]+  , 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 1,200,000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  , examples (NumeralValue 5000)+             [ "5 nghìn"+             , "năm nghìn"+             ]+  , examples (NumeralValue 200000)+             [ "hai trăm nghìn"+             ]+  , examples (NumeralValue 1000000000)+             [ "một tỷ"+             ]+  , examples (NumeralValue 21011)+             [ "hai mươi mốt nghìn không trăm mười một"+             ]+  , examples (NumeralValue 721012)+             [ "bảy trăm hai mươi mốt nghìn không trăm mười hai"+             ]+  ]
+ Duckling/Numeral/VI/Rules.hs view
@@ -0,0 +1,335 @@+-- 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 #-}++module Duckling.Numeral.VI.Rules+  ( rules ) where++import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++rulePowersOfTen :: Rule+rulePowersOfTen = Rule+  { name = "powers of tens"+  , pattern =+    [ regex "(tr\x0103m?|ngh\x00ecn?|tri\x1ec7u?|t\x1ef7?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "tr\x0103"   -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "tr\x0103m"  -> double 1e2 >>= withGrain 2 >>= withMultipliable+        "ngh\x00ec"  -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "ngh\x00ecn" -> double 1e3 >>= withGrain 3 >>= withMultipliable+        "tri\x1ec7"  -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "tri\x1ec7u" -> double 1e6 >>= withGrain 6 >>= withMultipliable+        "t"          -> double 1e9 >>= withGrain 9 >>= withMultipliable+        "t\x1ef7"    -> double 1e9 >>= withGrain 9 >>= withMultipliable+        _            -> Nothing+      _ -> Nothing+  }++ruleIntersectWithAnd :: Rule+ruleIntersectWithAnd = Rule+  { name = "intersect (with and)"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , regex "and"+    , numberWith TNumeral.multipliable not+    ]+  , 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+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> Nothing+  }++ruleNumeralsPrefixWithM :: Rule+ruleNumeralsPrefixWithM = Rule+  { name = "numbers prefix with -, âm"+  , pattern =+    [ regex "-|\x00e2m\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleNumerals2 :: Rule+ruleNumerals2 = Rule+  { name = "numbers 25 35 45 55 65 75 85 95"+  , pattern =+    [ oneOf [20, 30 .. 90]+    , regex "l\x0103m"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 5+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer 21..99"+  , 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+  }++ruleNumeralDot :: Rule+ruleNumeralDot = Rule+  { name = "number dot 1 9"+  , pattern =+    [ dimension Numeral+    , regex "ch\x1ea5m|ph\x1ea9y"+    , numberWith TNumeral.grain isNothing+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd1:_:Token Numeral nd2:_) ->+        double $ TNumeral.value nd1 + decimalsToDouble (TNumeral.value nd2)+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ numberWith (fromMaybe 0 . TNumeral.grain) (>1)+    , numberWith TNumeral.multipliable not+    ]+  , 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+    , numberWith TNumeral.multipliable id+    ]+  , prod = \tokens -> case tokens of+      (token1:token2:_) -> multiply token1 token2+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])(?=[\\W\\$\x20ac]|$)"+    ]+  , 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+  }++ruleNumeralNghn :: Rule+ruleNumeralNghn = Rule+  { name = "number nghìn"+  , pattern =+    [ numberBetween 1 1000+    , numberWith TNumeral.value (== 1000)+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2, TNumeral.grain = Just g}):+       _) -> double (v1 * v2) >>= withGrain g+      _ -> Nothing+  }++ruleInteger :: Rule+ruleInteger = Rule+  { name = "integer (0..19)"+  , pattern =+    [ regex "(kh\x00f4ng|m\x1ed9t|linh m\x1ed9t|l\x1ebb m\x1ed9t|hai|linh hai|l\x1ebb hai|ba|linh ba|l\x1ebb ba|b\x1ed1n|linh b\x1ed1n|l\x1ebb b\x1ed1n|n\x0103m|linh n\x0103m|l\x1ebb n\x0103m|s\x00e1u|l\x1ebb s\x00e1u|linh s\x00e1u|b\x1ea3y|l\x1ebb b\x1ea3y|linh b\x1ea3y|t\x00e1m|linh t\x00e1m|l\x1ebb t\x00e1m|ch\x00edn|linh ch\x00edn|l\x1ebb ch\x00edn|m\x01b0\x1eddi m\x1ed9t|m\x01b0\x1eddi hai|m\x01b0\x1eddi ba|m\x01b0\x1eddi b\x1ed1n|m\x01b0\x1eddi l\x0103m|m\x01b0\x1eddi s\x00e1u|m\x01b0\x1eddi b\x1ea3y|m\x01b0\x1eddi t\x00e1m|m\x01b0\x1eddi ch\x00edn|m\x01b0\x1eddi|linh m\x01b0\x1eddi)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "kh\x00f4ng" -> integer 0+        "m\x1ed9t" -> integer 1+        "linh m\x1ed9t" -> integer 1+        "l\x1ebb m\x1ed9t" -> integer 1+        "hai" -> integer 2+        "l\x1ebb hai" -> integer 2+        "linh hai" -> integer 2+        "ba" -> integer 3+        "l\x1ebb" -> integer 3+        "linh ba" -> integer 3+        "l\x1ebb b\x1ed1n" -> integer 4+        "linh b\x1ed1n" -> integer 4+        "b\x1ed1n" -> integer 4+        "n\x0103m" -> integer 5+        "l\x1ebb n\x0103m" -> integer 5+        "linh n\x0103m" -> integer 5+        "linh s\x00e1u" -> integer 6+        "s\x00e1u" -> integer 6+        "l\x1ebb s\x00e1u" -> integer 6+        "linh b\x1ea3y" -> integer 7+        "l\x1ebb b\x1ea3y" -> integer 7+        "b\x1ea3y" -> integer 7+        "l\x1ebb t\x00e1m" -> integer 8+        "linh t\x00e1m" -> integer 8+        "t\x00e1m" -> integer 8+        "l\x1ebb ch\x00edn" -> integer 9+        "ch\x00edn" -> integer 9+        "linh ch\x00edn" -> integer 9+        "linh m\x01b0\x1eddi" -> integer 10+        "m\x01b0\x1eddi" -> integer 10+        "l\x1ebb m\x01b0\x1eddi" -> integer 10+        "m\x01b0\x1eddi m\x1ed9t" -> integer 11+        "m\x01b0\x1eddi hai" -> integer 12+        "m\x01b0\x1eddi ba" -> integer 13+        "m\x01b0\x1eddi b\x1ed1n" -> integer 14+        "m\x01b0\x1eddi l\x0103m" -> integer 15+        "m\x01b0\x1eddi s\x00e1u" -> integer 16+        "m\x01b0\x1eddi b\x1ea3y" -> integer 17+        "m\x01b0\x1eddi t\x00e1m" -> integer 18+        "m\x01b0\x1eddi ch\x00edn" -> integer 19+        _ -> Nothing+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ regex "(hai m\x01b0\x01a1i|ba m\x01b0\x01a1i|b\x1ed1n m\x01b0\x01a1i|n\x0103m m\x01b0\x01a1i|s\x00e1u m\x01b0\x01a1i|b\x1ea3y m\x01b0\x01a1i|t\x00e1m m\x01b0\x01a1i|ch\x00edn m\x01b0\x01a1i)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "hai m\x01b0\x01a1i" -> integer 20+        "ba m\x01b0\x01a1i" -> integer 30+        "b\x1ed1n m\x01b0\x01a1i" -> integer 40+        "n\x0103m m\x01b0\x01a1i" -> integer 50+        "s\x00e1u m\x01b0\x01a1i" -> integer 60+        "b\x1ea3y m\x01b0\x01a1i" -> integer 70+        "t\x00e1m m\x01b0\x01a1i" -> integer 80+        "ch\x00edn m\x01b0\x01a1i" -> integer 90+        _ -> Nothing+      _ -> Nothing+  }++ruleNumerals :: Rule+ruleNumerals = Rule+  { name = "numbers 21 31 41 51 61 71 81 91"+  , pattern =+    [ oneOf [20, 30 .. 90]+    , regex "m\x1ed1t"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v + 1+      _ -> Nothing+  }++ruleT :: Rule+ruleT = Rule+  { name = "tá"+  , pattern =+    [ regex "t\x00e1"+    ]+  , prod = \_ -> integer 12 >>= withGrain 1 >>= withMultipliable+  }++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:_)):+       _) -> let fmt = Text.replace (Text.singleton ',') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger+  , ruleInteger2+  , ruleInteger3+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleIntersect+  , ruleIntersectWithAnd+  , ruleMultiply+  , ruleNumeralDot+  , ruleNumeralNghn+  , ruleNumerals+  , ruleNumerals2+  , ruleNumeralsPrefixWithM+  , ruleNumeralsSuffixesKMG+  , rulePowersOfTen+  , ruleT+  ]
+ Duckling/Numeral/ZH/Corpus.hs view
@@ -0,0 +1,109 @@+-- 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.ZH.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Numeral.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ZH}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (NumeralValue 0)+             [ "0"+             , "〇"+             , "零"+             , "零个"+             , "0个"+             ]+  , examples (NumeralValue 1)+             [ "1"+             , "一"+             , "一个"+             , "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 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"+             , "负1,200,000"+             , "负 1,200,000"+             , "負 1,200,000"+             , "负1200000"+             , "负 1200000"+             , "-1.2M"+             , "-1200K"+             , "-.0012G"+             ]+  ]
+ Duckling/Numeral/ZH/Rules.hs view
@@ -0,0 +1,201 @@+-- 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 #-}++module Duckling.Numeral.ZH.Rules+  ( rules ) where++import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import qualified Data.Text as Text+import Prelude+import Data.String++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++ruleInteger5 :: Rule+ruleInteger5 = Rule+  { name = "integer (0..10)"+  , pattern =+    [ regex "(\x3007|\x96f6|\x4e00|\x4e8c|\x4e24|\x5169|\x4e09|\x56db|\x4e94|\x516d|\x4e03|\x516b|\x4e5d|\x5341)(\x4e2a|\x500b)?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        HashMap.lookup match integerMap >>= integer+      _ -> Nothing+  }++integerMap :: HashMap.HashMap Text.Text Integer+integerMap = HashMap.fromList+  [ ( "\x3007", 0 )+  , ( "\x96f6", 0 )+  , ( "\x4e00", 1 )+  , ( "\x5169", 2 )+  , ( "\x4e24", 2 )+  , ( "\x4e8c", 2 )+  , ( "\x4e09", 3 )+  , ( "\x56db", 4 )+  , ( "\x4e94", 5 )+  , ( "\x516d", 6 )+  , ( "\x4e03", 7 )+  , ( "\x516b", 8 )+  , ( "\x4e5d", 9 )+  , ( "\x5341", 10 )+  ]+++ruleNumeralsPrefixWithNegativeOrMinus :: Rule+ruleNumeralsPrefixWithNegativeOrMinus = Rule+  { name = "numbers prefix with -, negative or minus"+  , pattern =+    [ regex "-|\x8d1f\\s?|\x8ca0\\s?"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral nd:_) -> double (TNumeral.value nd * (-1))+      _ -> Nothing+  }++ruleIntegerNumeric :: Rule+ruleIntegerNumeric = Rule+  { name = "integer (numeric)"+  , pattern =+    [ regex "(\\d{1,18})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        integer $ toInteger v+      _ -> 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:_)):_) ->+        parseDouble (Text.replace (Text.singleton ',') 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 True match+      _ -> Nothing+  }++ruleNumeral :: Rule+ruleNumeral = Rule+  { name = "<number>个"+  , pattern =+    [ dimension Numeral+    , regex "\x4e2a"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> Just token+      _ -> Nothing+  }++ruleInteger3 :: Rule+ruleInteger3 = Rule+  { name = "integer (20..90)"+  , pattern =+    [ numberBetween 2 10+    , regex "\x5341"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ v * 10+      _ -> Nothing+  }++ruleNumeralsSuffixesKMG :: Rule+ruleNumeralsSuffixesKMG = Rule+  { name = "numbers suffixes (K, M, G)"+  , pattern =+    [ dimension Numeral+    , regex "([kmg])"+    ]+  , 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+  }++ruleInteger4 :: Rule+ruleInteger4 = Rule+  { name = "integer 21..99"+  , pattern =+    [ oneOf [70, 20, 60, 50, 40, 90, 30, 80]+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v1}):+       Token Numeral (NumeralData {TNumeral.value = v2}):+       _) -> double $ v1 + v2+      _ -> Nothing+  }++ruleInteger2 :: Rule+ruleInteger2 = Rule+  { name = "integer (11..19)"+  , pattern =+    [ regex "\x5341"+    , numberBetween 1 10+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) -> double $ 10 + v+      _ -> 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:_)):+       _) -> let fmt = Text.replace (Text.singleton ',') Text.empty match+        in parseDouble fmt >>= double+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleDecimalNumeral+  , ruleDecimalWithThousandsSeparator+  , ruleInteger2+  , ruleInteger3+  , ruleInteger4+  , ruleInteger5+  , ruleIntegerNumeric+  , ruleIntegerWithThousandsSeparator+  , ruleNumeral+  , ruleNumeralsPrefixWithNegativeOrMinus+  , ruleNumeralsSuffixesKMG+  ]
+ Duckling/Ordinal/AR/Corpus.hs view
@@ -0,0 +1,29 @@+-- 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.Ordinal.AR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = AR}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 2)+           [ "الثاني"+           ]
+ Duckling/Ordinal/AR/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.AR.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Ordinal.Helpers+import Duckling.Types++ruleOrdinalsTh :: Rule+ruleOrdinalsTh = Rule+  { name = "ordinals 7th"+  , pattern =+    [ regex "(\x0633\x0627\x0628\x0639 | \x0633\x0627\x0628\x0639\x0629 | \x0627\x0644\x0633\x0627\x0628\x0639 | \x0627\x0644\x0633\x0627\x0628\x0639\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 7+  }++ruleOrdinalsSecond :: Rule+ruleOrdinalsSecond = Rule+  { name = "ordinals second"+  , pattern =+    [ regex "(\x062b\x0627\x0646\x064a|\x062b\x0627\x0646\x064a\x0629|\x0627\x0644\x062b\x0627\x0646\x064a|\x0627\x0644\x062b\x0627\x0646\x064a\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 2+  }++ruleOrdinalsFirst :: Rule+ruleOrdinalsFirst = Rule+  { name = "ordinals first"+  , pattern =+    [ regex "(\x0623\x0648\x0644|\x0627\x0644\x0623\x0648\x0644|\x0623\x0648\x0644\x0649|\x0627\x0644\x0623\x0648\x0644\x0649)"+    ]+  , prod = \_ -> Just $ ordinal 1+  }++ruleOrdinalsFirst5 :: Rule+ruleOrdinalsFirst5 = Rule+  { name = "ordinals first"+  , pattern =+    [ regex "(\x0633\x0627\x062f\x0633 | \x0633\x0627\x062f\x0633\x0629 | \x0627\x0644\x0633\x0627\x062f\x0633 | \x0627\x0644\x0633\x0627\x062f\x0633\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 6+  }++ruleOrdinalsTh2 :: Rule+ruleOrdinalsTh2 = Rule+  { name = "ordinals 8th"+  , pattern =+    [ regex "(\x062b\x0627\x0645\x0646 | \x062b\x0627\x0645\x0646\x0629 | \x0627\x0644\x062b\x0627\x0645\x0646 | \x0627\x0644\x062b\x0627\x0645\x0646\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 8+  }++ruleOrdinalsFirst2 :: Rule+ruleOrdinalsFirst2 = Rule+  { name = "ordinals first"+  , pattern =+    [ regex "(\x062b\x0627\x0644\x062b|\x062b\x0627\x0644\x062b\x0629|\x0627\x0644\x062b\x0627\x0644\x062b|\x0627\x0644\x062b\x0627\x0644\x062b\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 3+  }++ruleOrdinalsTh4 :: Rule+ruleOrdinalsTh4 = Rule+  { name = "ordinals 10th"+  , pattern =+    [ regex "(\x0639\x0627\x0634\x0631 | \x0639\x0627\x0634\x0631\x0629 | \x0627\x0644\x0639\x0627\x0634\x0631 | \x0627\x0644\x0639\x0627\x0634\x0631\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 10+  }++ruleOrdinalsTh3 :: Rule+ruleOrdinalsTh3 = Rule+  { name = "ordinals 9th"+  , pattern =+    [ regex "(\x062a\x0627\x0633\x0639 | \x062a\x0627\x0633\x0639\x0629 | \x0627\x0644\x062a\x0627\x0633\x0639 | \x0627\x0644\x062a\x0627\x0633\x0639\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 9+  }++ruleOrdinalsFirst4 :: Rule+ruleOrdinalsFirst4 = Rule+  { name = "ordinals first"+  , pattern =+    [ regex "(\x062e\x0627\x0645\x0633 | \x0627\x0644\x062e\x0627\x0645\x0633 | \x062e\x0627\x0645\x0633\x0629 | \x0627\x0644\x062e\x0627\x0645\x0633\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 5+  }++ruleOrdinalsFirst3 :: Rule+ruleOrdinalsFirst3 = Rule+  { name = "ordinals first"+  , pattern =+    [ regex "(\x0631\x0627\x0628\x0639|\x0631\x0627\x0628\x0639\x0629 | \x0627\x0644\x0631\x0627\x0628\x0639|\x0627\x0644\x0631\x0627\x0628\x0639\x0629)"+    ]+  , prod = \_ -> Just $ ordinal 4+  }++rules :: [Rule]+rules =+  [ ruleOrdinalsFirst+  , ruleOrdinalsFirst2+  , ruleOrdinalsFirst3+  , ruleOrdinalsFirst4+  , ruleOrdinalsFirst5+  , ruleOrdinalsSecond+  , ruleOrdinalsTh+  , ruleOrdinalsTh2+  , ruleOrdinalsTh3+  , ruleOrdinalsTh4+  ]
+ Duckling/Ordinal/DA/Corpus.hs view
@@ -0,0 +1,31 @@+-- 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.Ordinal.DA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = DA}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 4)+           [ "4."+           , "fjerde"+           , "Fjerde"+           ]
+ Duckling/Ordinal/DA/Rules.hs view
@@ -0,0 +1,85 @@+-- 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 #-}++module Duckling.Ordinal.DA.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstst :: Rule+ruleOrdinalsFirstst = Rule+  { name = "ordinals (first..31st)"+  , pattern =+    [ regex "(f\x00f8rste|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)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "f\x00f8rste" -> 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+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.|ste?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        Just $ ordinal v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstst+  ]
+ Duckling/Ordinal/DE/Corpus.hs view
@@ -0,0 +1,31 @@+-- 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.Ordinal.DE.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = DE}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 4)+           [ "vierter"+           , "4ter"+           , "Vierter"+           ]
+ Duckling/Ordinal/DE/Rules.hs view
@@ -0,0 +1,93 @@+-- 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 #-}++module Duckling.Ordinal.DE.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , 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\x00f6lfter|dreizenter|vierzehnter|f\x00fcnfzehnter|sechzenter|siebzehnter|achtzehnter|neunzehnter)"+    ]+  , 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\x00fcnftes" -> Just $ ordinal 5+        "f\x00fcnfter" -> Just $ ordinal 5+        "f\x00fcnfte" -> 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\x00f6lfter" -> Just $ ordinal 12+        "dreizehnter" -> Just $ ordinal 13+        "vierzehnter" -> Just $ ordinal 14+        "f\x00fcnfzehnter" -> Just $ ordinal 15+        "sechzehnter" -> Just $ ordinal 16+        "siebzehnter" -> Just $ ordinal 17+        "achtzehnter" -> Just $ ordinal 18+        "neunzehnter" -> Just $ ordinal 19+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.| ?(te(n|r|s)?)|(ste(n|r|s)?))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        v <- parseInt match+        Just $ ordinal v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/EN/Corpus.hs view
@@ -0,0 +1,65 @@+-- 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.Ordinal.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Ordinal.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "first"+             , "1st"+             ]+  , examples (OrdinalData 2)+             [ "second"+             , "2nd"+             ]+  , examples (OrdinalData 3)+             [ "third"+             , "3rd"+             ]+  , examples (OrdinalData 4)+             [ "fourth"+             , "4th"+             ]+  , examples (OrdinalData 8)+             [ "eighth"+             , "8th"+             ]+  , examples (OrdinalData 25)+             [ "twenty-fifth"+             , "25th"+             ]+  , examples (OrdinalData 31)+             [ "thirty-first"+             , "31st"+             ]+  , examples (OrdinalData 42)+             [ "forty-second"+             , "42nd"+             ]+  , examples (OrdinalData 77)+            [ "seventy-seventh"+            , "77th"+            ]+  , examples (OrdinalData 90)+            [ "ninetieth"+            , "90th"+            ]+  ]
+ Duckling/Ordinal/EN/Rules.hs view
@@ -0,0 +1,109 @@+-- 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 #-}++module Duckling.Ordinal.EN.Rules+  ( rules ) where++import Control.Monad (join)+import Data.HashMap.Strict ( HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++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+  [ ( "first", 1 )+  , ( "second", 2 )+  , ( "third", 3 )+  , ( "fourth", 4 )+  , ( "fifth", 5 )+  , ( "sixth", 6 )+  , ( "seventh", 7 )+  , ( "eighth", 8 )+  , ( "ninth", 9 )+  , ( "tenth", 10 )+  , ( "eleventh", 11 )+  , ( "twelfth", 12 )+  , ( "thirteenth", 13 )+  , ( "fourteenth", 14 )+  , ( "fifteenth", 15 )+  , ( "sixteenth", 16 )+  , ( "seventeenth", 17 )+  , ( "eighteenth", 18 )+  , ( "nineteenth", 19 )+  , ( "twentieth", 20 )+  , ( "thirtieth", 30 )+  , ( "fortieth", 40 )+  , ( "fiftieth", 50 )+  , ( "sixtieth", 60 )+  , ( "seventieth", 70 )+  , ( "eightieth", 80 )+  , ( "ninetieth", 90 )+  ]++cardinalsMap :: HashMap Text Int+cardinalsMap = HashMap.fromList+  [ ( "twenty", 20 )+  , ( "thirty", 30 )+  , ( "forty", 40 )+  , ( "fifty", 50 )+  , ( "sixty", 60 )+  , ( "seventy", 70 )+  , ( "eighty", 80 )+  , ( "ninety", 90 )+  ]+++ruleOrdinals :: Rule+ruleOrdinals = Rule+  { name = "ordinals (first..twentieth,thirtieth,...)"+  , pattern = [regex "(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|thirtieth|fortieth|fiftieth|sixtieth|seventieth|eightieth|ninetieth)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap+      _ -> Nothing+    }++ruleCompositeOrdinals :: Rule+ruleCompositeOrdinals = Rule+  { name = "ordinals (composite, e.g., eighty-seven)"+  , pattern = [regex "(twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)\\-(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth)"]+  , prod = \tokens -> case tokens of+      (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+) ?(st|nd|rd|th)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinals+  , ruleCompositeOrdinals+  , ruleOrdinalDigits+  ]
+ Duckling/Ordinal/ES/Rules.hs view
@@ -0,0 +1,94 @@+-- 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 #-}++module Duckling.Ordinal.ES.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 )+  , ( "primero" , 1 )+  , ( "primeros" , 1 )+  , ( "primera" , 1 )+  , ( "primeras" , 1 )+  , ( "segundo" , 2 )+  , ( "segunda" , 2 )+  , ( "segundas" , 2 )+  , ( "segundos" , 2 )+  , ( "terceros" , 3 )+  , ( "tercera" , 3 )+  , ( "terceras" , 3 )+  , ( "tercero" , 3 )+  , ( "tercer" , 3 )+  , ( "cuarta" , 4 )+  , ( "cuartas" , 4 )+  , ( "cuartos" , 4 )+  , ( "cuarto" , 4 )+  , ( "quinto" , 5 )+  , ( "quinta" , 5 )+  , ( "quintas" , 5 )+  , ( "quintos" , 5 )+  , ( "sextos" , 6 )+  , ( "sexto" , 6 )+  , ( "sexta" , 6 )+  , ( "sextas" , 6 )+  , ( "s\x00e9ptimas" , 7 )+  , ( "septimas" , 7 )+  , ( "s\x00e9ptima" , 7 )+  , ( "septimos" , 7 )+  , ( "septima" , 7 )+  , ( "s\x00e9ptimo" , 7 )+  , ( "s\x00e9ptimos" , 7 )+  , ( "septimo" , 7 )+  , ( "octavas" , 8 )+  , ( "octavo" , 8 )+  , ( "octavos" , 8 )+  , ( "octava" , 8 )+  , ( "novenos" , 9 )+  , ( "novena" , 9 )+  , ( "noveno" , 9 )+  , ( "novenas" , 9 )+  , ( "d\x00e9cimos" , 10 )+  , ( "decimo" , 10 )+  , ( "decimos" , 10 )+  , ( "d\x00e9cimo" , 10 )+  , ( "decimas" , 10 )+  , ( "d\x00e9cima" , 10 )+  , ( "decima" , 10 )+  , ( "d\x00e9cimas" , 10 )+  ]++ruleOrdinalsPrimero :: Rule+ruleOrdinalsPrimero = Rule+  { name = "ordinals (primero..10)"+  , pattern =+    [ regex "(primer|tercer(os?|as?)?|(primer|segund|cuart|quint|sext|s[e\x00e9]ptim|octav|noven|d[e\x00e9]cim)(os?|as?))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalsPrimero+  ]
+ Duckling/Ordinal/ET/Corpus.hs view
@@ -0,0 +1,31 @@+-- 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.Ordinal.ET.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ET}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 4)+           [ "4."+           , "neljas"+           , "Neljas"+           ]
+ Duckling/Ordinal/ET/Rules.hs view
@@ -0,0 +1,71 @@+-- 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 #-}++module Duckling.Ordinal.ET.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , pattern =+    [ regex "(esimene|teine|kolmas|neljas|viies|kuues|seitsmes|kaheksas|\x00fcheksas|k\x00fcmnes|\x00fcheteistk\x00fcmnes|kaheteistk\x00fcmnes|kolmeteistk\x00fcmnes|neljateistk\x00fcmnes|viieteistk\x00fcmnes|kuueteistk\x00fcmnes|seitsmeteistk\x00fcmnes|kaheksateistk\x00fcmnes|\x00fcheksateistk\x00fcmnes)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "esimene" -> Just $ ordinal 1+        "teine" -> Just $ ordinal 2+        "kolmas" -> Just $ ordinal 3+        "neljas" -> Just $ ordinal 4+        "viies" -> Just $ ordinal 5+        "kuues" -> Just $ ordinal 6+        "seitsmes" -> Just $ ordinal 7+        "kaheksas" -> Just $ ordinal 8+        "\x00fcheksas" -> Just $ ordinal 9+        "k\x00fcmnes" -> Just $ ordinal 10+        "\x00fcheteistk\x00fcmnes" -> Just $ ordinal 11+        "kaheteistk\x00fcmnes" -> Just $ ordinal 12+        "kolmeteistk\x00fcmnes" -> Just $ ordinal 13+        "neljateistk\x00fcmnes" -> Just $ ordinal 14+        "viieteistk\x00fcmnes" -> Just $ ordinal 15+        "kuueteistk\x00fcmnes" -> Just $ ordinal 16+        "seitsmeteistk\x00fcmnes" -> Just $ ordinal 17+        "kaheksateistk\x00fcmnes" -> Just $ ordinal 18+        "\x00fcheksateistk\x00fcmnes" -> Just $ ordinal 19+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)\\."+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/FR/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "1er"+             , "1ere"+             , "1ère"+             , "Premier"+             , "première"+             ]+  , examples (OrdinalData 2)+             [ "deuxieme"+             , "deuxième"+             , "2e"+             , "second"+             , "2eme"+             , "2ème"+             ]+  , examples (OrdinalData 11)+             [ "onzieme"+             , "onzième"+             , "11eme"+             , "11ème"+             , "11e"+             ]+  ]
+ Duckling/Ordinal/FR/Rules.hs view
@@ -0,0 +1,96 @@+-- 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 #-}++module Duckling.Ordinal.FR.Rules+  ( rules ) where++import Data.HashMap.Strict ( HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsPremierseiziemeMap :: HashMap Text Int+ruleOrdinalsPremierseiziemeMap = HashMap.fromList+  [ ( "premi\x00e8re"   , 1 )+  , ( "premiere"        , 1 )+  , ( "premier"         , 1 )+  , ( "deuxi\x00e8me"   , 2 )+  , ( "deuxieme"        , 2 )+  , ( "second"          , 2 )+  , ( "seconde"         , 2 )+  , ( "troisi\x00e8me"  , 3 )+  , ( "troisieme"       , 3 )+  , ( "quatrieme"       , 4 )+  , ( "quatri\x00e8me"  , 4 )+  , ( "cinquieme"       , 5 )+  , ( "cinqui\x00e8me"  , 5 )+  , ( "sixi\x00e8me"    , 6 )+  , ( "sixieme"         , 6 )+  , ( "septieme"        , 7 )+  , ( "septi\x00e8me"   , 7 )+  , ( "huiti\x00e8me"   , 8 )+  , ( "huitieme"        , 8 )+  , ( "neuvieme"        , 9 )+  , ( "neuvi\x00e8me"   , 9 )+  , ( "dixi\x00e8me"    , 10 )+  , ( "dixieme"         , 10 )+  , ( "onzi\x00e8me"    , 11 )+  , ( "onzieme"         , 11 )+  , ( "douzieme"        , 12 )+  , ( "douzi\x00e8me"   , 12 )+  , ( "treizieme"       , 13 )+  , ( "treizi\x00e8me"  , 13 )+  , ( "quatorzi\x00e8me", 14 )+  , ( "quatorzieme"     , 14 )+  , ( "quinzi\x00e8me"  , 15 )+  , ( "quinzieme"       , 15 )+  , ( "seizieme"        , 16 )+  , ( "seizi\x00e8me"   , 16 )+  ]++ruleOrdinalsPremierseizieme :: Rule+ruleOrdinalsPremierseizieme = Rule+  { name = "ordinals (premier..seizieme)"+  , pattern =+    [ regex "(premi(ere?|\x00e8re)|(deux|trois|quatr|cinqu|six|sept|huit|neuv|dix|onz|douz|treiz|quatorz|quinz|seiz)i(e|\x00e8)me|seconde?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ruleOrdinalsPremierseiziemeMap+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) ?(ere?|\x00e8re|\x00e8me|eme|e)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        n <- parseInt match+        Just $ ordinal n+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsPremierseizieme+  ]
+ Duckling/Ordinal/GA/Corpus.hs view
@@ -0,0 +1,46 @@+-- 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.Ordinal.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 6)+             [ "séu"+             ]+  , examples (OrdinalData 1)+             [ "chead"+             , "t-aonu"+             , "t-aonú"+             , "Aonu"+             , "aonú"+             ]+  , examples (OrdinalData 30)+             [ "tríochadú"+             , "triochadú"+             , "tríochadu"+             ]+  , examples (OrdinalData 50)+             [ "caogadu"+             , "caogadú"+             ]+  ]
+ Duckling/Ordinal/GA/Rules.hs view
@@ -0,0 +1,121 @@+-- 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 #-}++module Duckling.Ordinal.GA.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsChadDaraEtc :: Rule+ruleOrdinalsChadDaraEtc = Rule+  { name = "ordinals (chéad, dara, etc.)"+  , pattern =+    [ regex "(ch(\x00e9|e)ad|aon(\x00fa|u)|t-aon(\x00fa|u)|dara|tr(\x00ed|i)(\x00fa|u)|ceathr(\x00fa|u)|c(\x00fa|u)igi(\x00fa|u)|s(\x00e9|e)(\x00fa|u)|seacht(\x00fa|u)|ocht(\x00fa|u)|t-ocht(\x00fa|u)|nao(\x00fa|u)|deichi(\x00fa|u)|fichi(\x00fa|u)|tr(\x00ed|i)ochad(\x00fa|u)|daichead(\x00fa|u)|caogad(\x00fa|u)|seascad(\x00fa|u)|seacht(\x00f3|o)d(\x00fa|u)|ocht(\x00f3|o)d(\x00fa|u)|t-ocht(\x00f3|o)d(\x00fa|u)|n(\x00f3|o)chad(\x00fa|u)|c(\x00e9|e)ad(\x00fa|u)|mili(\x00fa|u)|milli(\x00fa|u)n(\x00fa|u))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "t-aonu" -> Just $ ordinal 1+        "aonu" -> Just $ ordinal 1+        "aon\x00fa" -> Just $ ordinal 1+        "ch\x00e9ad" -> Just $ ordinal 1+        "chead" -> Just $ ordinal 1+        "t-aon\x00fa" -> Just $ ordinal 1+        "dara" -> Just $ ordinal 2+        "tri\x00fa" -> Just $ ordinal 3+        "tr\x00edu" -> Just $ ordinal 3+        "tr\x00ed\x00fa" -> Just $ ordinal 3+        "triu" -> Just $ ordinal 3+        "ceathr\x00fa" -> Just $ ordinal 4+        "ceathru" -> Just $ ordinal 4+        "c\x00faigiu" -> Just $ ordinal 5+        "c\x00faigi\x00fa" -> Just $ ordinal 5+        "cuigiu" -> Just $ ordinal 5+        "cuigi\x00fa" -> Just $ ordinal 5+        "s\x00e9u" -> Just $ ordinal 6+        "s\x00e9\x00fa" -> Just $ ordinal 6+        "seu" -> Just $ ordinal 6+        "se\x00fa" -> Just $ ordinal 6+        "seachtu" -> Just $ ordinal 7+        "seacht\x00fa" -> Just $ ordinal 7+        "t-ocht\x00fa" -> Just $ ordinal 8+        "ochtu" -> Just $ ordinal 8+        "t-ochtu" -> Just $ ordinal 8+        "ocht\x00fa" -> Just $ ordinal 8+        "naou" -> Just $ ordinal 9+        "nao\x00fa" -> Just $ ordinal 9+        "deichiu" -> Just $ ordinal 10+        "deichi\x00fa" -> Just $ ordinal 10+        "fichiu" -> Just $ ordinal 20+        "fichi\x00fa" -> Just $ ordinal 20+        "tr\x00edochadu" -> Just $ ordinal 30+        "triochadu" -> Just $ ordinal 30+        "tr\x00edochad\x00fa" -> Just $ ordinal 30+        "triochad\x00fa" -> Just $ ordinal 30+        "daichead\x00fa" -> Just $ ordinal 40+        "daicheadu" -> Just $ ordinal 40+        "caogadu" -> Just $ ordinal 50+        "caogad\x00fa" -> Just $ ordinal 50+        "seascadu" -> Just $ ordinal 60+        "seascad\x00fa" -> Just $ ordinal 60+        "seachtodu" -> Just $ ordinal 70+        "seachtod\x00fa" -> Just $ ordinal 70+        "seacht\x00f3d\x00fa" -> Just $ ordinal 70+        "seacht\x00f3du" -> Just $ ordinal 70+        "ocht\x00f3du" -> Just $ ordinal 80+        "ochtodu" -> Just $ ordinal 80+        "t-ochtodu" -> Just $ ordinal 80+        "t-ocht\x00f3d\x00fa" -> Just $ ordinal 80+        "t-ochtod\x00fa" -> Just $ ordinal 80+        "ocht\x00f3d\x00fa" -> Just $ ordinal 80+        "t-ocht\x00f3du" -> Just $ ordinal 80+        "ochtod\x00fa" -> Just $ ordinal 80+        "n\x00f3chad\x00fa" -> Just $ ordinal 90+        "n\x00f3chadu" -> Just $ ordinal 90+        "nochad\x00fa" -> Just $ ordinal 90+        "nochadu" -> Just $ ordinal 90+        "c\x00e9ad\x00fa" -> Just $ ordinal 100+        "cead\x00fa" -> Just $ ordinal 100+        "ceadu" -> Just $ ordinal 100+        "c\x00e9adu" -> Just $ ordinal 100+        "miliu" -> Just $ ordinal 1000+        "mili\x00fa" -> Just $ ordinal 1000+        "milliun\x00fa" -> Just $ ordinal 1000000+        "milliunu" -> Just $ ordinal 1000000+        "milli\x00fanu" -> Just $ ordinal 1000000+        "milli\x00fan\x00fa" -> Just $ ordinal 1000000+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) ?(a|d|(\x00fa|u))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsChadDaraEtc+  ]
+ Duckling/Ordinal/HE/Corpus.hs view
@@ -0,0 +1,29 @@+-- 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.Ordinal.HE.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HE}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 4)+             [ "ארבעה"+             ]+  ]
+ Duckling/Ordinal/HE/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.HE.Rules+  ( rules ) where++import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Ordinal.Types (OrdinalData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Ordinal.Types as TOrdinal++ruleOrdinal4 :: Rule+ruleOrdinal4 = Rule+  { name = "ordinal 4"+  , pattern =+    [ regex "(\x05d0\x05e8\x05d1\x05e2\x05d4|\x05e8\x05d1\x05d9\x05e2\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 4+  }++ruleOrdinal9 :: Rule+ruleOrdinal9 = Rule+  { name = "ordinal 9"+  , pattern =+    [ regex "(\x05ea\x05e9\x05e2\x05d4|\x05ea\x05e9\x05d9\x05e2\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 9+  }++ruleOrdinal10 :: Rule+ruleOrdinal10 = Rule+  { name = "ordinal 10"+  , pattern =+    [ regex "(\x05e2\x05e9\x05e8\x05d4|\x05e2\x05e9\x05d9\x05e8\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 10+  }++ruleOrdinal12 :: Rule+ruleOrdinal12 = Rule+  { name = "ordinal 12"+  , pattern =+    [ regex "(\x05e9\x05e0\x05d9\x05d9\x05dd \x05e2\x05e9\x05e8|\x05ea\x05e8\x05d9 \x05e2\x05e9\x05e8)"+    ]+  , prod = \_ -> Just $ ordinal 12+  }++ruleOrdinal17 :: Rule+ruleOrdinal17 = Rule+  { name = "ordinal 17"+  , pattern =+    [ regex "(\x05e9\x05d1\x05e2(\x05d4)? \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 17+  }++ruleOrdinal18 :: Rule+ruleOrdinal18 = Rule+  { name = "ordinal 18"+  , pattern =+    [ regex "(\x05e9\x05de\x05d5\x05e0\x05d4 \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 18+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) "+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++ruleOrdinal15 :: Rule+ruleOrdinal15 = Rule+  { name = "ordinal 15"+  , pattern =+    [ regex "(\x05d7\x05de\x05d9\x05e9\x05d4 \x05e2\x05e9\x05e8|\x05d7\x05de\x05e9 \x05e2\x05e9\x05e8\x05d4?)"+    ]+  , prod = \_ -> Just $ ordinal 15+  }++ruleOrdinal5 :: Rule+ruleOrdinal5 = Rule+  { name = "ordinal 5"+  , pattern =+    [ regex "(\x05d7\x05de\x05d9\x05e9\x05d9|\x05d7\x05de\x05d9\x05e9\x05d4)"+    ]+  , prod = \_ -> Just $ ordinal 5+  }++ruleOrdinal16 :: Rule+ruleOrdinal16 = Rule+  { name = "ordinal 16"+  , pattern =+    [ regex "(\x05e9\x05e9(\x05d4)? \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 16+  }++ruleOrdinal14 :: Rule+ruleOrdinal14 = Rule+  { name = "ordinal 14"+  , pattern =+    [ regex "(\x05d0\x05e8\x05d1\x05e2(\x05d4)? \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 14+  }++ruleOrdinal20 :: Rule+ruleOrdinal20 = Rule+  { name = "ordinal 20..90"+  , pattern =+    [ regex "(\x05e2\x05e9\x05e8\x05d9\x05dd|\x05e9\x05dc\x05d5\x05e9\x05d9\x05dd|\x05d0\x05e8\x05d1\x05e2\x05d9\x05dd|\x05d7\x05de\x05d9\x05e9\x05d9\x05dd|\x05e9\x05d9\x05e9\x05d9\x05dd|\x05e9\x05d1\x05e2\x05d9\x05dd|\x05e9\x05de\x05d5\x05e0\x05d9\x05dd|\x05ea\x05e9\x05e2\x05d9\x05dd)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x05e2\x05e9\x05e8\x05d9\x05dd" -> Just $ ordinal 20+        "\x05e9\x05dc\x05d5\x05e9\x05d9\x05dd" -> Just $ ordinal 30+        "\x05d0\x05e8\x05d1\x05e2\x05d9\x05dd" -> Just $ ordinal 40+        "\x05d7\x05de\x05d9\x05e9\x05d9\x05dd" -> Just $ ordinal 50+        "\x05e9\x05d9\x05e9\x05d9\x05dd" -> Just $ ordinal 60+        "\x05e9\x05d1\x05e2\x05d9\x05dd" -> Just $ ordinal 70+        "\x05e9\x05de\x05d5\x05e0\x05d9\x05dd" -> Just $ ordinal 80+        "\x05ea\x05e9\x05e2\x05d9\x05dd" -> Just $ ordinal 90+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinal :: Rule+ruleOrdinal = Rule+  { name = "ordinal 1"+  , pattern =+    [ regex "(\x05d0\x05d7\x05d3|\x05e8\x05d0\x05e9\x05d5\x05df)"+    ]+  , prod = \_ -> Just $ ordinal 1+  }++ruleOrdinal13 :: Rule+ruleOrdinal13 = Rule+  { name = "ordinal 13"+  , pattern =+    [ regex "(\x05e9\x05dc\x05d5\x05e9(\x05d4)? \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 13+  }++ruleOrdinal7 :: Rule+ruleOrdinal7 = Rule+  { name = "ordinal 7"+  , pattern =+    [ regex "(\x05e9\x05d1\x05e2\x05d4|\x05e9\x05d1\x05d9\x05e2\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 7+  }++ruleOrdinal8 :: Rule+ruleOrdinal8 = Rule+  { name = "ordinal 8"+  , pattern =+    [ regex "(\x05e9\x05de\x05d5\x05e0\x05d4|\x05e9\x05de\x05d9\x05e0\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 8+  }++ruleOrdinal2 :: Rule+ruleOrdinal2 = Rule+  { name = "ordinal 2"+  , pattern =+    [ regex "(\x05e9\x05ea\x05d9\x05d9\x05dd|\x05e9\x05e0\x05d9\x05d9\x05dd|\x05e9\x05e0\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 2+  }++ruleOrdinal11 :: Rule+ruleOrdinal11 = Rule+  { name = "ordinal 11"+  , pattern =+    [ regex "(\x05d0\x05d7\x05d3 \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 11+  }++ruleOrdinal3 :: Rule+ruleOrdinal3 = Rule+  { name = "ordinal 3"+  , pattern =+    [ regex "(\x05e9\x05dc\x05d5\x05e9\x05d4|\x05e9\x05dc\x05d9\x05e9\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 3+  }++ruleOrdinal6 :: Rule+ruleOrdinal6 = Rule+  { name = "ordinal 6"+  , pattern =+    [ regex "(\x05e9\x05e9\x05d4|\x05e9\x05d9\x05e9\x05d9)"+    ]+  , prod = \_ -> Just $ ordinal 6+  }++ruleOrdinal19 :: Rule+ruleOrdinal19 = Rule+  { name = "ordinal 19"+  , pattern =+    [ regex "(\x05ea\x05e9\x05e2(\x05d4)? \x05e2\x05e9\x05e8(\x05d4)?)"+    ]+  , prod = \_ -> Just $ ordinal 19+  }++ruleCompositeWithAnd :: Rule+ruleCompositeWithAnd = Rule+  { name = "ordinal composition (with and)"+  , pattern =+    [ dimension Ordinal+    , regex "\x05d5"+    , dimension Ordinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v1}):+       _:+       Token Ordinal (OrdinalData {TOrdinal.value = v2}):+       _) -> Just . ordinal $ v1 + v2+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCompositeWithAnd+  , ruleOrdinal+  , ruleOrdinal10+  , ruleOrdinal11+  , ruleOrdinal12+  , ruleOrdinal13+  , ruleOrdinal14+  , ruleOrdinal15+  , ruleOrdinal16+  , ruleOrdinal17+  , ruleOrdinal18+  , ruleOrdinal19+  , ruleOrdinal2+  , ruleOrdinal20+  , ruleOrdinal3+  , ruleOrdinal4+  , ruleOrdinal5+  , ruleOrdinal6+  , ruleOrdinal7+  , ruleOrdinal8+  , ruleOrdinal9+  , ruleOrdinalDigits+  ]
+ Duckling/Ordinal/HR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 3)+             [ "3."+             , "trece"+             , "treći"+             , "trećeg"+             ]+  , examples (OrdinalData 4)+             [ "4."+             , "4ti"+             , "4ta"+             , "četvrti"+             , "četvrta"+             , "četvrto"+             , "cetvrti"+             , "cetvrta"+             , "cetvrto"+             ]+  , examples (OrdinalData 6)+             [ "6."+             , "6ti"+             , "šesto"+             , "šestoga"+             , "sestog"+             ]+  ]
+ Duckling/Ordinal/HR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.HR.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+import qualified Data.Text as Text+import qualified Data.HashMap.Strict as HashMap++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Ordinal.Types (OrdinalData (..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Ordinal.Types as TOrdinal++ordinalsMap :: HashMap Text Int+ordinalsMap = HashMap.fromList+  [ ("prva", 1)+  , ("prvi", 1)+  , ("prvoga", 1)+  , ("prvo", 1)+  , ("prvog", 1)+  , ("drugoga", 2)+  , ("drugo", 2)+  , ("druga", 2)+  , ("drugi", 2)+  , ("drugog", 2)+  , ("tre\263i", 3)+  , ("tre\263ega", 3)+  , ("trece", 3)+  , ("tre\263eg", 3)+  , ("treca", 3)+  , ("tre\263a", 3)+  , ("treci", 3)+  , ("\269etvrti", 4)+  , ("\269etvrtoga", 4)+  , ("cetvrtoga", 4)+  , ("cetvrto", 4)+  , ("cetvrtog", 4)+  , ("cetvrti", 4)+  , ("\269etvrtog", 4)+  , ("cetvrta", 4)+  , ("\269etvrto", 4)+  , ("\269etvrta", 4)+  , ("peto", 5)+  , ("peti", 5)+  , ("petoga", 5)+  , ("petog", 5)+  , ("peta", 5)+  , ("sesti", 6)+  , ("\353estoga", 6)+  , ("\353estog", 6)+  , ("sestoga", 6)+  , ("sesta", 6)+  , ("\353esta", 6)+  , ("\353esto", 6)+  , ("\353esti", 6)+  , ("sesto", 6)+  , ("sestog", 6)+  , ("sedmi", 7)+  , ("sedmog", 7)+  , ("sedma", 7)+  , ("sedmo", 7)+  , ("sedmoga", 7)+  , ("osmo", 8)+  , ("osmog", 8)+  , ("osma", 8)+  , ("osmi", 8)+  , ("osmoga", 8)+  , ("devetog", 9)+  , ("deveta", 9)+  , ("deveto", 9)+  , ("devetoga", 9)+  , ("deveti", 9)+  , ("desetoga", 10)+  , ("desetog", 10)+  , ("deseta", 10)+  , ("deseto", 10)+  , ("deseti", 10)+  , ("jedanaestoga", 11)+  , ("jedanaesta", 11)+  , ("jedanaesti", 11)+  , ("jedanaesto", 11)+  , ("jedanaestog", 11)+  , ("dvanaesto", 12)+  , ("dvanaestog", 12)+  , ("dvanaesti", 12)+  , ("dvanaesta", 12)+  , ("dvanaestoga", 12)+  , ("trinaesta", 13)+  , ("trinaestoga", 13)+  , ("trinaestog", 13)+  , ("trinaesto", 13)+  , ("trinaesti", 13)+  , ("cetrnaestog", 14)+  , ("cetrnaesto", 14)+  , ("cetrnaesti", 14)+  , ("\269etrnaestoga", 14)+  , ("cetrnaesta", 14)+  , ("\269etrnaesto", 14)+  , ("\269etrnaesta", 14)+  , ("cetrnaestoga", 14)+  , ("\269etrnaesti", 14)+  , ("\269etrnaestog", 14)+  , ("petnaestog", 15)+  , ("petnaesto", 15)+  , ("petnaesta", 15)+  , ("petnaesti", 15)+  , ("petnaestoga", 15)+  , ("sesnaesto", 16)+  , ("sesnaestog", 16)+  , ("sesnaesti", 16)+  , ("\353esnaestoga", 16)+  , ("sesnaesta", 16)+  , ("\353esnaesto", 16)+  , ("sesnaestoga", 16)+  , ("\353esnaesti", 16)+  , ("\353esnaesta", 16)+  , ("\353esnaestog", 16)+  , ("sedamnaesto", 17)+  , ("sedamnaestoga", 17)+  , ("sedamnaesti", 17)+  , ("sedamnaesta", 17)+  , ("sedamnaestog", 17)+  , ("osamnaestoga", 18)+  , ("osamnaestog", 18)+  , ("osamnaesti", 18)+  , ("osamnaesta", 18)+  , ("osamnaesto", 18)+  , ("devetnaestoga", 19)+  , ("devetnaestog", 19)+  , ("devetnaesto", 19)+  , ("devetnaesti", 19)+  , ("devetnaesta", 19)+  ]++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , pattern =+    [ regex "(prv(i|a|o(ga?)?)|drug(i|a|o(ga?)?)|tre(c|\x0107)(i|a|e(ga?)?)|(\x010d|c)etvrt(i|a|o(ga?)?)|pet(i|a|o(ga?)?)|(\x0161|s)est(i|a|o(ga?)?)|sedm(i|a|o(ga?)?)|osm(i|a|o(ga?)?)|devet(i|a|o(ga?)?)|deset(i|a|o(ga?)?)|jedanaest(i|a|o(ga?)?)|dvanaest(i|a|o(ga?)?)|trinaest(i|a|o(ga?)?)|(c|\x010d)etrnaest(i|a|o(ga?)?)|petnaest(i|a|o(ga?)?)|(s|\x0161)esnaest(i|a|o(ga?)?)|sedamnaest(i|a|o(ga?)?)|osamnaest(i|a|o(ga?)?)|devetnaest(i|a|o(ga?)?))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsMap+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.| ?(t(i|a)(n|r|s)?)|(ste(n|r|s)?))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/Helpers.hs view
@@ -0,0 +1,27 @@+-- 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.Ordinal.Helpers+  ( ordinal+  ) where++import Prelude++import Duckling.Dimensions.Types+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Types++-- -----------------------------------------------------------------+-- Patterns++-- -----------------------------------------------------------------+-- Production++ordinal :: Int -> Token+ordinal x = Token Ordinal OrdinalData {TOrdinal.value = x}
+ Duckling/Ordinal/ID/Corpus.hs view
@@ -0,0 +1,38 @@+-- 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.Ordinal.ID.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ID}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 4)+             [ "ke-4"+             , "keempat"+             ]+  , examples (OrdinalData 10)+             [ "Kesepuluh"+             ]+  , examples (OrdinalData 3)+             [ "ketiga"+             , "ke-00003"+             ]+  ]
+ Duckling/Ordinal/ID/Rules.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.ID.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinals :: Rule+ruleOrdinals = Rule+  { name = "ordinals"+  , pattern =+    [ regex "(pertama|kedua|ketiga|keempat|kelima|keenam|ketujuh|kedelapan|kesembilan|kesepuluh)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "pertama" -> Just $ ordinal 1+        "kedua" -> Just $ ordinal 2+        "ketiga" -> Just $ ordinal 3+        "keempat" -> Just $ ordinal 4+        "kelima" -> Just $ ordinal 5+        "keenam" -> Just $ ordinal 6+        "ketujuh" -> Just $ ordinal 7+        "kedelapan" -> Just $ ordinal 8+        "kesembilan" -> Just $ ordinal 9+        "kesepuluh" -> Just $ ordinal 10+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalsDigits :: Rule+ruleOrdinalsDigits = Rule+  { name = "ordinals (digits)"+  , pattern =+    [ regex "ke-0*(\\d+)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinals+  , ruleOrdinalsDigits+  ]
+ Duckling/Ordinal/IT/Corpus.hs view
@@ -0,0 +1,87 @@+-- 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.Ordinal.IT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = IT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "primo"+             , "prima"+             , "1°"+             , "1ª"+             ]+  , examples (OrdinalData 2)+             [ "secondo"+             , "seconda"+             , "2°"+             , "2ª"+             ]+  , examples (OrdinalData 3)+             [ "terzo"+             , "Terza"+             , "3°"+             , "3ª"+             ]+  , examples (OrdinalData 4)+             [ "quarto"+             , "quarta"+             , "4°"+             , "4ª"+             ]+  , examples (OrdinalData 5)+             [ "quinto"+             , "quinta"+             , "5°"+             , "5ª"+             ]+  , examples (OrdinalData 6)+             [ "sesto"+             , "sesta"+             , "6°"+             , "6ª"+             ]+  , examples (OrdinalData 7)+             [ "settimo"+             , "settima"+             , "7°"+             , "7ª"+             ]+  , examples (OrdinalData 8)+             [ "ottavo"+             , "ottava"+             , "8°"+             , "8ª"+             ]+  , examples (OrdinalData 9)+             [ "nono"+             , "nona"+             , "9°"+             , "9ª"+             ]+  , examples (OrdinalData 10)+             [ "decimo"+             , "decima"+             , "10°"+             , "10ª"+             ]+  ]
+ Duckling/Ordinal/IT/Rules.hs view
@@ -0,0 +1,92 @@+-- 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 #-}++module Duckling.Ordinal.IT.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsPrimo :: Rule+ruleOrdinalsPrimo = Rule+  { name = "ordinals (primo..10)"+  , pattern =+    [ regex "((prim|second|terz|quart|quint|sest|settim|ottav|non|decim)(o|a|i|e))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "primi" -> Just $ ordinal 1+        "prima" -> Just $ ordinal 1+        "primo" -> Just $ ordinal 1+        "prime" -> Just $ ordinal 1+        "seconda" -> Just $ ordinal 2+        "secondi" -> Just $ ordinal 2+        "seconde" -> Just $ ordinal 2+        "secondo" -> Just $ ordinal 2+        "terze" -> Just $ ordinal 3+        "terzi" -> Just $ ordinal 3+        "terzo" -> Just $ ordinal 3+        "terza" -> Just $ ordinal 3+        "quarte" -> Just $ ordinal 4+        "quarto" -> Just $ ordinal 4+        "quarta" -> Just $ ordinal 4+        "quarti" -> Just $ ordinal 4+        "quinto" -> Just $ ordinal 5+        "quinta" -> Just $ ordinal 5+        "quinti" -> Just $ ordinal 5+        "quinte" -> Just $ ordinal 5+        "sesti" -> Just $ ordinal 6+        "seste" -> Just $ ordinal 6+        "sesta" -> Just $ ordinal 6+        "sesto" -> Just $ ordinal 6+        "settimi" -> Just $ ordinal 7+        "settima" -> Just $ ordinal 7+        "settimo" -> Just $ ordinal 7+        "settime" -> Just $ ordinal 7+        "ottavo" -> Just $ ordinal 8+        "ottava" -> Just $ ordinal 8+        "ottavi" -> Just $ ordinal 8+        "ottave" -> Just $ ordinal 8+        "none" -> Just $ ordinal 9+        "noni" -> Just $ ordinal 9+        "nona" -> Just $ ordinal 9+        "nono" -> Just $ ordinal 9+        "decimo" -> Just $ ordinal 10+        "decima" -> Just $ ordinal 10+        "decime" -> Just $ ordinal 10+        "decimi" -> Just $ ordinal 10+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) ?(\x00aa|\x00b0|\x00b0)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsPrimo+  ]
+ Duckling/Ordinal/JA/Corpus.hs view
@@ -0,0 +1,29 @@+-- 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.Ordinal.JA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = JA}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 7)+           [ "第七"+           ]
+ Duckling/Ordinal/JA/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Ordinal.JA.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Ordinal.Helpers+import Duckling.Types++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "\x7b2c"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . ordinal $ floor v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  ]
+ Duckling/Ordinal/KO/Corpus.hs view
@@ -0,0 +1,38 @@+-- 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.Ordinal.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 25)+             [ "스물다섯번째"+             , "이십오번째"+             ]+  , examples (OrdinalData 1)+             [ "첫번째"+             , "첫째"+             ]+  , examples (OrdinalData 4)+             [ "네째번"+             ]+  ]
+ Duckling/Ordinal/KO/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Ordinal.KO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Ordinal.Helpers+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Types++ruleOrdinals :: Rule+ruleOrdinals = Rule+  { name = "ordinals (첫번째)"+  , pattern =+    [ dimension Numeral+    , regex "\xbc88\xc9f8|\xc9f8(\xbc88)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        Just . ordinal $ floor v+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinals+  ]
+ Duckling/Ordinal/NB/Corpus.hs view
@@ -0,0 +1,40 @@+-- 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.Ordinal.NB.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NB}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 4)+             [ "4."+             , "fjerde"+             , "fJerde"+             ]+  , examples (OrdinalData 15)+             [ "15."+             , "femtende"+             ]+  , examples (OrdinalData 5)+             [ "5."+             , "femte"+             ]+  ]
+ Duckling/Ordinal/NB/Rules.hs view
@@ -0,0 +1,93 @@+-- 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 #-}++module Duckling.Ordinal.NB.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstst :: Rule+ruleOrdinalsFirstst = Rule+  { name = "ordinals (first..31st)"+  , pattern =+    [ regex "(f\x00f8rste|andre|tredje|fjerde|femtende|femte|sjette|syvende|\x00e5ttende|niende|tiende|ellevte|tolvte|trettende|fjortende|sekstende|syttende|attende|nittende|tyvende|tjuende|enogtyvende|toogtyvende|treogtyvende|fireogtyvende|femogtyvende|seksogtyvende|syvogtyvende|\x00e5tteogtyvende|niogtyvende|enogtjuende|toogtjuende|treogtjuende|fireogtjuende|femogtjuende|seksogtjuende|syvogtjuende|\x00e5tteogtyvend|niogtjuende|tredefte|enogtredefte)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "f\x00f8rste" -> Just $ ordinal 1+        "andre" -> Just $ ordinal 2+        "tredje" -> Just $ ordinal 3+        "fjerde" -> Just $ ordinal 4+        "femte" -> Just $ ordinal 5+        "sjette" -> Just $ ordinal 6+        "syvende" -> Just $ ordinal 7+        "\x00e5ttende" -> Just $ ordinal 8+        "niende" -> Just $ ordinal 9+        "tiende" -> Just $ ordinal 10+        "ellevte" -> 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+        "tjuende" -> Just $ ordinal 20+        "enogtjuende" -> Just $ ordinal 21+        "enogtyvende" -> Just $ ordinal 21+        "toogtyvende" -> Just $ ordinal 22+        "toogtjuende" -> Just $ ordinal 22+        "treogtyvende" -> Just $ ordinal 23+        "treogtjuende" -> Just $ ordinal 23+        "fireogtjuende" -> Just $ ordinal 24+        "fireogtyvende" -> Just $ ordinal 24+        "femogtyvende" -> Just $ ordinal 25+        "femogtjuende" -> Just $ ordinal 25+        "seksogtjuende" -> Just $ ordinal 26+        "seksogtyvende" -> Just $ ordinal 26+        "syvogtyvende" -> Just $ ordinal 27+        "syvogtjuende" -> Just $ ordinal 27+        "\x00e5tteogtyvende" -> Just $ ordinal 28+        "\x00e5tteogtjuende" -> Just $ ordinal 28+        "niogtyvende" -> Just $ ordinal 29+        "niogtjuende" -> Just $ ordinal 29+        "tredefte" -> Just $ ordinal 30+        "enogtredefte" -> Just $ ordinal 31+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.|ste?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstst+  ]
+ Duckling/Ordinal/NL/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.NL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = NL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "1ste"+             , "eerste"+             ]+  , examples (OrdinalData 4)+             [ "4de"+             , "vierde"+             ]+  , examples (OrdinalData 17)+             [ "Zeventiende"+             , "17de"+             ]+  ]
+ Duckling/Ordinal/NL/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.NL.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++zeroNineteenMap :: HashMap Text Int+zeroNineteenMap = HashMap.fromList+  [ ("eerste", 1)+  , ("tweede", 2)+  , ("derde", 3)+  , ("vierde", 4)+  , ("vijfde", 5)+  , ("zesde", 6)+  , ("zevende", 7)+  , ("achste", 8)+  , ("negende", 9)+  , ("tiende", 10)+  , ("elfde", 11)+  , ("twaalfde", 12)+  , ("dertiende", 13)+  , ("veertiende", 14)+  , ("vijftiende", 15)+  , ("zestiende", 16)+  , ("zeventiende", 17)+  , ("achtiende", 18)+  , ("negentiende", 19)+  ]++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , pattern =+    [ regex "(eerste|tweede|derde|vierde|vijfde|zeste|zevende|achtste|negende|tiende|elfde|twaalfde|veertiende|vijftiende|zestiende|zeventiende|achtiende|negentiende)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) zeroNineteenMap+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.| ?(ste|de))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/PL/Corpus.hs view
@@ -0,0 +1,30 @@+-- 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.Ordinal.PL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PL}, allExamples)++allExamples :: [Example]+allExamples =+  examples (OrdinalData 4)+           [ "4ty"+           , "czwarty"+           ]
+ Duckling/Ordinal/PL/Rules.hs view
@@ -0,0 +1,318 @@+-- 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 #-}++module Duckling.Ordinal.PL.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Types++ruleThOrdinalNoSpace :: Rule+ruleThOrdinalNoSpace = Rule+  { name = "24th ordinal no space"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)czwart(y|ego|emu|ym|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 24+  }++ruleThOrdinal16 :: Rule+ruleThOrdinal16 = Rule+  { name = "31-39th ordinal"+  , pattern =+    [ regex "trzydziest(ym|y|ego|emu|(a|\x0105)|ej)( |-)?"+    , dimension Ordinal+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        Just . ordinal $ 30 + v+      _ -> Nothing+  }++ruleThOrdinal3 :: Rule+ruleThOrdinal3 = Rule+  { name = "10th ordinal"+  , pattern =+    [ regex "dziesi(a|\x0105)t(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 10+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)( |-)?(szy|sza|szym|ego|go|szego|gi(ego|ej)?|st(a|y|ej)|t(ej|y|ego)|ci(ego)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++ruleThOrdinal8 :: Rule+ruleThOrdinal8 = Rule+  { name = "15th ordinal"+  , pattern =+    [ regex "pi(e|\x0119)tnast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 15+  }++ruleThOrdinal13 :: Rule+ruleThOrdinal13 = Rule+  { name = "20th ordinal"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 20+  }++ruleThOrdinal4 :: Rule+ruleThOrdinal4 = Rule+  { name = "11th ordinal"+  , pattern =+    [ regex "jedenast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 11+  }++ruleFifthOrdinal :: Rule+ruleFifthOrdinal = Rule+  { name = "fifth ordinal"+  , pattern =+    [ regex "pi(a|\x0105)t(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 5+  }++ruleThOrdinal11 :: Rule+ruleThOrdinal11 = Rule+  { name = "18th ordinal"+  , pattern =+    [ regex "osiemnast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 18+  }++ruleSecondOrdinal :: Rule+ruleSecondOrdinal = Rule+  { name = "second ordinal"+  , pattern =+    [ regex "drugi?(ego|emu|m|(a|\x0105)|ej)?"+    ]+  , prod = \_ -> Just $ ordinal 2+  }++ruleNdOrdinalNoSpace :: Rule+ruleNdOrdinalNoSpace = Rule+  { name = "22nd ordinal no space"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)drugi?(ego|emu|m|(a|\x0105)|ej)?"+    ]+  , prod = \_ -> Just $ ordinal 22+  }++ruleSeventhOrdinal :: Rule+ruleSeventhOrdinal = Rule+  { name = "seventh ordinal"+  , pattern =+    [ regex "si(o|\x00f3)dm(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 7+  }++ruleStOrdinalNoSpace :: Rule+ruleStOrdinalNoSpace = Rule+  { name = "21st ordinal no space"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)pierw?sz(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 21+  }++ruleThOrdinal7 :: Rule+ruleThOrdinal7 = Rule+  { name = "14th ordinal"+  , pattern =+    [ regex "czternast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 14+  }++ruleThOrdinal2 :: Rule+ruleThOrdinal2 = Rule+  { name = "9th ordinal"+  , pattern =+    [ regex "dziewi(a|\x0105)t(ym|y|ego|em|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 9+  }++ruleThOrdinal9 :: Rule+ruleThOrdinal9 = Rule+  { name = "16th ordinal"+  , pattern =+    [ regex "szesnast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 16+  }++ruleThOrdinal :: Rule+ruleThOrdinal = Rule+  { name = "8th ordinal"+  , pattern =+    [ regex "(o|\x00f3|\x00d3)sm(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 8+  }++ruleThOrdinal14 :: Rule+ruleThOrdinal14 = Rule+  { name = "21-29th ordinal"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)( |-)?"+    , dimension Ordinal+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        Just . ordinal $ 20 + v+      _ -> Nothing+  }++ruleThOrdinal10 :: Rule+ruleThOrdinal10 = Rule+  { name = "17th ordinal"+  , pattern =+    [ regex "siedemnast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 17+  }++ruleRdOrdinalNoSpace :: Rule+ruleRdOrdinalNoSpace = Rule+  { name = "23rd ordinal no space"+  , pattern =+    [ regex "dwudziest(ym|y|ego|emu|(a|\x0105)|ej)trzeci(ego|ch|emu|m|mi|ej|(a|\x0105))?"+    ]+  , prod = \_ -> Just $ ordinal 23+  }++ruleThOrdinal5 :: Rule+ruleThOrdinal5 = Rule+  { name = "12th ordinal"+  , pattern =+    [ regex "dwunast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 12+  }++ruleThOrdinal6 :: Rule+ruleThOrdinal6 = Rule+  { name = "13th ordinal"+  , pattern =+    [ regex "trzynast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 13+  }++ruleFirstOrdinal :: Rule+ruleFirstOrdinal = Rule+  { name = "first ordinal"+  , pattern =+    [ regex "pierw?sz(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 1+  }++ruleSixthOrdinal :: Rule+ruleSixthOrdinal = Rule+  { name = "sixth ordinal"+  , pattern =+    [ regex "sz(o|\x00f3)st(y|ego|emu|m|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 6+  }++ruleFourthOrdinal :: Rule+ruleFourthOrdinal = Rule+  { name = "fourth ordinal"+  , pattern =+    [ regex "czwart(y|ego|emu|ym|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 4+  }++ruleThOrdinal15 :: Rule+ruleThOrdinal15 = Rule+  { name = "30th ordinal"+  , pattern =+    [ regex "trzydziest(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 30+  }++ruleThOrdinal12 :: Rule+ruleThOrdinal12 = Rule+  { name = "19th ordinal"+  , pattern =+    [ regex "dziewi(\x0119|e)tnast(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \_ -> Just $ ordinal 19+  }++ruleThirdOrdinal :: Rule+ruleThirdOrdinal = Rule+  { name = "third ordinal"+  , pattern =+    [ regex "trzeci(ego|ch|emu|m|mi|ej|(a|\x0105))?"+    ]+  , prod = \_ -> Just $ ordinal 3+  }++rules :: [Rule]+rules =+  [ ruleFifthOrdinal+  , ruleFirstOrdinal+  , ruleFourthOrdinal+  , ruleNdOrdinalNoSpace+  , ruleOrdinalDigits+  , ruleRdOrdinalNoSpace+  , ruleSecondOrdinal+  , ruleSeventhOrdinal+  , ruleSixthOrdinal+  , ruleStOrdinalNoSpace+  , ruleThOrdinal+  , ruleThOrdinal10+  , ruleThOrdinal11+  , ruleThOrdinal12+  , ruleThOrdinal13+  , ruleThOrdinal14+  , ruleThOrdinal15+  , ruleThOrdinal16+  , ruleThOrdinal2+  , ruleThOrdinal3+  , ruleThOrdinal4+  , ruleThOrdinal5+  , ruleThOrdinal6+  , ruleThOrdinal7+  , ruleThOrdinal8+  , ruleThOrdinal9+  , ruleThOrdinalNoSpace+  , ruleThirdOrdinal+  ]
+ Duckling/Ordinal/PT/Corpus.hs view
@@ -0,0 +1,40 @@+-- 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.Ordinal.PT.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "primeira"+             , "primeiros"+             ]+  , examples (OrdinalData 2)+             [ "Segundo"+             , "segundas"+             ]+  , examples (OrdinalData 7)+             [ "setimo"+             , "sétimas"+             ]+  ]
+ Duckling/Ordinal/PT/Rules.hs view
@@ -0,0 +1,87 @@+-- 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 #-}++module Duckling.Ordinal.PT.Rules+  ( rules ) where++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++ruleOrdinalsPrimeiro :: Rule+ruleOrdinalsPrimeiro = Rule+  { name = "ordinals (primeiro..10)"+  , pattern =+    [ regex "((primeir|segund|quart|quint|sext|s(e|\x00e9)tim|oitav|non|d(e|\x00e9)cim)(os?|as?))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "primeira" -> Just $ ordinal 1+        "primeiros" -> Just $ ordinal 1+        "primeiras" -> Just $ ordinal 1+        "primeiro" -> Just $ ordinal 1+        "segundo" -> Just $ ordinal 2+        "segunda" -> Just $ ordinal 2+        "segundas" -> Just $ ordinal 2+        "segundos" -> Just $ ordinal 2+        "terceiros" -> Just $ ordinal 3+        "terceiro" -> Just $ ordinal 3+        "terceiras" -> Just $ ordinal 3+        "terceira" -> Just $ ordinal 3+        "quartos" -> Just $ ordinal 4+        "quarto" -> Just $ ordinal 4+        "quarta" -> Just $ ordinal 4+        "quartas" -> Just $ ordinal 4+        "quinto" -> Just $ ordinal 5+        "quinta" -> Just $ ordinal 5+        "quintas" -> Just $ ordinal 5+        "quintos" -> Just $ ordinal 5+        "sextos" -> Just $ ordinal 6+        "sexto" -> Just $ ordinal 6+        "sexta" -> Just $ ordinal 6+        "sextas" -> Just $ ordinal 6+        "setimas" -> Just $ ordinal 7+        "s\x00e9tima" -> Just $ ordinal 7+        "setimo" -> Just $ ordinal 7+        "setimos" -> Just $ ordinal 7+        "setima" -> Just $ ordinal 7+        "s\x00e9timos" -> Just $ ordinal 7+        "s\x00e9timo" -> Just $ ordinal 7+        "s\x00e9timas" -> Just $ ordinal 7+        "oitavas" -> Just $ ordinal 8+        "oitava" -> Just $ ordinal 8+        "oitavo" -> Just $ ordinal 8+        "oitavos" -> Just $ ordinal 8+        "nonos" -> Just $ ordinal 9+        "nona" -> Just $ ordinal 9+        "nono" -> Just $ ordinal 9+        "nonas" -> Just $ ordinal 9+        "d\x00e9cimos" -> Just $ ordinal 10+        "decimo" -> Just $ ordinal 10+        "decimos" -> Just $ ordinal 10+        "d\x00e9cimo" -> Just $ ordinal 10+        "decimas" -> Just $ ordinal 10+        "d\x00e9cima" -> Just $ ordinal 10+        "decima" -> Just $ ordinal 10+        "d\x00e9cimas" -> Just $ ordinal 10+        _ -> Nothing+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalsPrimeiro+  ]
+ Duckling/Ordinal/RO/Corpus.hs view
@@ -0,0 +1,68 @@+-- 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.Ordinal.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "primul"+             , "prima"+             ]+  , examples (OrdinalData 2)+             [ "al doilea"+             , "al doi-lea"+             , "al doi lea"+             , "al 2-lea"+             , "al 2 lea"+             , "a 2 a"+             , "a 2-a"+             , "a doua"+             ]+  , examples (OrdinalData 3)+             [ "al treilea"+             , "al trei-lea"+             , "a treia"+             , "a 3-lea"+             , "a 3a"+             ]+  , examples (OrdinalData 4)+             [ "a patra"+             , "a patru-lea"+             ]+  , examples (OrdinalData 6)+             [ "al saselea"+             , "al șaselea"+             , "al sase-lea"+             , "al șase-lea"+             , "a sasea"+             , "a șase a"+             ]+  , examples (OrdinalData 9)+             [ "al noualea"+             , "al noua-lea"+             , "al noua lea"+             , "al nouălea"+             , "al nouă lea"+             , "a noua"+             ]+  ]
+ Duckling/Ordinal/RO/Rules.hs view
@@ -0,0 +1,93 @@+-- 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 #-}++module Duckling.Ordinal.RO.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++rulePrimulDouaPatraNoua :: Rule+rulePrimulDouaPatraNoua = Rule+ { name = "special ordinals"+ , pattern =+   [ regex "(prim(a|ul)|a (patra|[dn]oua))"+   ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "prima"   -> Just $ ordinal 1+        "primul"  -> Just $ ordinal 1+        "a doua"  -> Just $ ordinal 2+        "a patra" -> Just $ ordinal 4+        "a noua"  -> Just $ ordinal 9+        _         -> Nothing+      _ -> Nothing+ }++-- We can't have a generic rule of the form "al?" + Numeral + "(le)?a"+-- It wouldn't match "al optlea"++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinals (digits)"+  , pattern =+    [ regex "al?\\s0*(\\d+)[ -]?(le)?a"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> parseInt match+      _ -> Nothing+  }++ordinalMap :: HashMap Text Int+ordinalMap = HashMap.fromList+  [ ("doi", 2)+  , ("trei", 3)+  , ("patru", 4)+  , ("cinci", 5)+  , ("sase", 6)+  , ("\537ase", 6)+  , ("sapte", 7)+  , ("\537apte", 7)+  , ("opt", 8)+  , ("noua", 9)+  , ("nou\x0103", 9)+  ]++ruleSpelledOutOrdinals :: Rule+ruleSpelledOutOrdinals = Rule+  { name = "spelled out ordinals"+  , pattern =+    [ regex "al?\\s(doi|trei|patru|cinci|(s|\x0219)a(s|pt)e|opt|nou(a|\x0103))[ -]?(le)?a"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalMap+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , rulePrimulDouaPatraNoua+  , ruleSpelledOutOrdinals+  ]
+ Duckling/Ordinal/RU/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.RU.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RU}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "первый"+             , "первая"+             , "первое"+             , "1ая"+             , "1-ая"+             , "1ый"+             , "1-ый"+             , "1ое"+             , "1-ое"+             ]+  , examples (OrdinalData 4)+             [ "четвертый"+             , "четвертая"+             , "четвертое"+             , "4ый"+             , "4ая"+             , "4ое"+             , "4-ый"+             , "4-ая"+             , "4-ое"+             ]+  , examples (OrdinalData 15)+             [ "пятнадцатый"+             , "15й"+             , "15-й"+             ]+  , examples (OrdinalData 21)+             [ "21й"+             , "21-й"+             , "двадцать первый"+             ]+  , examples (OrdinalData 31)+             [ "31ый"+             , "31-ый"+             , "тридцать первый"+             ]+  , examples (OrdinalData 48)+             [ "48ое"+             , "48-ое"+             , "сорок восьмое"+             ]+  , examples (OrdinalData 99)+             [ "99ый"+             , "99-й"+             , "девяносто девятый"+             ]+  ]
+ Duckling/Ordinal/RU/Rules.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 GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.RU.Rules+  ( rules ) where++import Control.Monad (join)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , pattern =+    [ regex "(\x043f\x0435\x0440\x0432|\x0432\x0442\x043e\x0440|\x0442\x0440\x0435\x0442|\x0447\x0435\x0442\x0432\x0435\x0440\x0442|\x043f\x044f\x0442|\x0448\x0435\x0441\x0442|\x0441\x0435\x0434\x044c\x043c|\x0432\x043e\x0441\x044c\x043c|\x0434\x0435\x0432\x044f\x0442|\x0434\x0435\x0441\x044f\x0442|\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x0430\x0442|\x0434\x0432\x0435\x043d\x0430\x0434\x0446\x0430\x0442|\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x0430\x0442|\x0447\x0435\x0442\x044b\x0440\x043d\x0430\x0434\x0446\x0430\x0442|\x043f\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442|\x0448\x0435\x0441\x0442\x043d\x0430\x0434\x0446\x0430\x0442|\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442|\x0432\x043e\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442|\x0434\x0435\x0432\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442|\x0434\x0432\x0430\x0434\x0446\x0430\x0442)(\x044b\x0439|\x043e\x0439|\x0438\x0439|\x0430\x044f|\x043e\x0435)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\x043f\x0435\x0440\x0432" -> Just $ ordinal 1+        "\x0432\x0442\x043e\x0440" -> Just $ ordinal 2+        "\x0442\x0440\x0435\x0442" -> Just $ ordinal 3+        "\x0447\x0435\x0442\x0432\x0435\x0440\x0442" -> Just $ ordinal 4+        "\x043f\x044f\x0442" -> Just $ ordinal 5+        "\x0448\x0435\x0441\x0442" -> Just $ ordinal 6+        "\x0441\x0435\x0434\x044c\x043c" -> Just $ ordinal 7+        "\x0432\x043e\x0441\x044c\x043c" -> Just $ ordinal 8+        "\x0434\x0435\x0432\x044f\x0442" -> Just $ ordinal 9+        "\x0434\x0435\x0441\x044f\x0442" -> Just $ ordinal 10+        "\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 11+        "\x0434\x0432\x0435\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 12+        "\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 13+        "\x0447\x0435\x0442\x044b\x0440\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 14+        "\x043f\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 15+        "\x0448\x0435\x0441\x0442\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 16+        "\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 17+        "\x0432\x043e\x0441\x0435\x043c\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 18+        "\x0434\x0435\x0432\x044f\x0442\x043d\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 19+        "\x0434\x0432\x0430\x0434\x0446\x0430\x0442" -> Just $ ordinal 20+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinal :: Rule+ruleOrdinal = Rule+  { name = "ordinal 21..99"+  , pattern =+    [ regex "(\x0434\x0432\x0430\x0434\x0446\x0430\x0442\x044c|\x0442\x0440\x0438\x0434\x0446\x0430\x0442\x044c|\x0441\x043e\x0440\x043e\x043a|\x043f\x044f\x0442\x044c\x0434\x0435\x0441\x044f\x0442|\x0448\x0435\x0441\x0442\x044c\x0434\x0435\x0441\x044f\x0442|\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442|\x0432\x043e\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442|\x0434\x0435\x0432\x044f\x043d\x043e\x0441\x0442\x043e)"+    , regex "(\x043f\x0435\x0440\x0432|\x0432\x0442\x043e\x0440|\x0442\x0440\x0435\x0442|\x0447\x0435\x0442\x0432\x0435\x0440\x0442|\x043f\x044f\x0442|\x0448\x0435\x0441\x0442|\x0441\x0435\x0434\x044c\x043c|\x0432\x043e\x0441\x044c\x043c|\x0434\x0435\x0432\x044f\x0442)(\x044b\x0439|\x043e\x0439|\x0438\x0439|\x0430\x044f|\x043e\x0435)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+         dozen <- case Text.toLower m1 of+           "\x0434\x0432\x0430\x0434\x0446\x0430\x0442\x044c" -> Just 20+           "\x0442\x0440\x0438\x0434\x0446\x0430\x0442\x044c" -> Just 30+           "\x0441\x043e\x0440\x043e\x043a" -> Just 40+           "\x043f\x044f\x0442\x044c\x0434\x0435\x0441\x044f\x0442" -> Just 50+           "\x0448\x0435\x0441\x0442\x044c\x0434\x0435\x0441\x044f\x0442" -> Just 60+           "\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442" -> Just 70+           "\x0432\x043e\x0441\x0435\x043c\x044c\x0434\x0435\x0441\x044f\x0442" -> Just 80+           "\x0434\x0435\x0432\x044f\x043d\x043e\x0441\x0442\x043e" -> Just 90+           _ -> Nothing+         unit <- case Text.toLower m2 of+           "\x043f\x0435\x0440\x0432" -> Just 1+           "\x0432\x0442\x043e\x0440" -> Just 2+           "\x0442\x0440\x0435\x0442" -> Just 3+           "\x0447\x0435\x0442\x0432\x0435\x0440\x0442" -> Just 4+           "\x043f\x044f\x0442" -> Just 5+           "\x0448\x0435\x0441\x0442" -> Just 6+           "\x0441\x0435\x0434\x044c\x043c" -> Just 7+           "\x0432\x043e\x0441\x044c\x043c" -> Just 8+           "\x0434\x0435\x0432\x044f\x0442" -> Just 9+           _ -> Nothing+         Just . ordinal $ dozen + unit+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)-?((\x044b|\x043e|\x0438)?\x0439|\x0430\x044f|\x043e\x0435)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinal+  , ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/SV/Corpus.hs view
@@ -0,0 +1,43 @@+-- 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.Ordinal.SV.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = SV}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "förste"+             , "första"+             , "1:a"+             , "1:e"+             ]+  , examples (OrdinalData 10)+             [ "tionde"+             , "10."+             , "10"+             ]+  , examples (OrdinalData 26)+             [ "seksogtjuende"+             , "Seksogtyvende"+             , "26e"+             ]+  ]
+ Duckling/Ordinal/SV/Rules.hs view
@@ -0,0 +1,94 @@+-- 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 #-}++module Duckling.Ordinal.SV.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ruleOrdinalsFirstst :: Rule+ruleOrdinalsFirstst = Rule+  { name = "ordinals (first..31st)"+  , pattern =+    [ regex "(f\x00f6rste|f\x00f6rsta|andra|tredje|fj\x00e4rde|femte|sj\x00e4tte|sjunde|\x00e5ttonde|nionde|tionde|ellevte|tolfte|trettonde|fjortonde|femtonde|sekstende|syttende|attende|nittende|tyvende|tjuende|enogtyvende|toogtyvende|treogtyvende|fireogtyvende|femogtyvende|seksogtyvende|syvogtyvende|\x00e5tteogtyvende|niogtyvende|enogtjuende|toogtjuende|treogtjuende|fireogtjuende|femogtjuende|seksogtjuende|syvogtjuende|\x00e5tteogtyvend|niogtjuende|tredefte|enogtredefte)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "f\x00f6rsta" -> Just $ ordinal 1+        "f\x00f6rste" -> Just $ ordinal 1+        "andra" -> Just $ ordinal 2+        "tredje" -> Just $ ordinal 3+        "fj\x00e4rde" -> Just $ ordinal 4+        "femte" -> Just $ ordinal 5+        "sj\x00e4tte" -> Just $ ordinal 6+        "sjunde" -> Just $ ordinal 7+        "\x00e5ttonde" -> Just $ ordinal 8+        "nionde" -> Just $ ordinal 9+        "tionde" -> Just $ ordinal 10+        "ellevte" -> Just $ ordinal 11+        "tolfte" -> Just $ ordinal 12+        "trettonde" -> Just $ ordinal 13+        "fjortonde" -> Just $ ordinal 14+        "femtonde" -> Just $ ordinal 15+        "sekstende" -> Just $ ordinal 16+        "syttende" -> Just $ ordinal 17+        "attende" -> Just $ ordinal 18+        "nittende" -> Just $ ordinal 19+        "tyvende" -> Just $ ordinal 20+        "tjuende" -> Just $ ordinal 20+        "enogtjuende" -> Just $ ordinal 21+        "enogtyvende" -> Just $ ordinal 21+        "toogtyvende" -> Just $ ordinal 22+        "toogtjuende" -> Just $ ordinal 22+        "treogtyvende" -> Just $ ordinal 23+        "treogtjuende" -> Just $ ordinal 23+        "fireogtjuende" -> Just $ ordinal 24+        "fireogtyvende" -> Just $ ordinal 24+        "femogtyvende" -> Just $ ordinal 25+        "femogtjuende" -> Just $ ordinal 25+        "seksogtjuende" -> Just $ ordinal 26+        "seksogtyvende" -> Just $ ordinal 26+        "syvogtyvende" -> Just $ ordinal 27+        "syvogtjuende" -> Just $ ordinal 27+        "\x00e5tteogtyvende" -> Just $ ordinal 28+        "\x00e5tteogtjuende" -> Just $ ordinal 28+        "niogtyvende" -> Just $ ordinal 29+        "niogtjuende" -> Just $ ordinal 29+        "tredefte" -> Just $ ordinal 30+        "enogtredefte" -> Just $ ordinal 31+        _ -> Nothing+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)(\\.|e|\\:[ae])?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstst+  ]
+ Duckling/Ordinal/TR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.TR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = TR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 4)+             [ "4üncü"+             , "dördüncü"+             , "4."+             , "4'üncü"+             ]+  , examples (OrdinalData 8)+             [ "sekizinci"+             ]+  , examples (OrdinalData 23)+             [ "yirmi üçüncü"+             ]+  ]
+ Duckling/Ordinal/TR/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.TR.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ordinals :: [Text]+ordinals =+  [ "birinci"+  , "ikinci"+  , "\x00fc\x00e7\x00fcnc\x00fc"+  , "d\x00f6rd\x00fcnc\x00fc"+  , "be\x015finci"+  , "alt\x0131nc\x0131"+  , "yedinci"+  , "sekizinci"+  , "dokuzuncu"+  , "onuncu"+  , "on birinci"+  , "on ikinci"+  , "on \x00fc\x00e7\x00fcnc\x00fc"+  , "on d\x00f6rd\x00fcnc\x00fc"+  , "on be\x015finci"+  , "on alt\x0131nc\x0131"+  , "on yedinci"+  , "on sekizinci"+  , "on dokuzuncu"+  , "yirminci"+  , "yirmi birinci"+  , "yirmi ikinci"+  , "yirmi \x00fc\x00e7\x00fcnc\x00fc"+  , "yirmi d\x00f6rd\x00fcnc\x00fc"+  , "yirmi be\x015finci"+  , "yirmi alt\x0131nc\x0131"+  , "yirmi yedinci"+  , "yirmi sekizinci"+  , "yirmi dokuzuncu"+  , "otuzuncu"+  , "otuz birinci"+  ]++ordinalsHashMap :: HashMap Text Int+ordinalsHashMap = HashMap.fromList $ zip ordinals [1..]++ruleOrdinalsFirstst :: Rule+ruleOrdinalsFirstst = Rule+  { name = "ordinals (first..31st)"+  , pattern =+    [ regex . Text.unpack $+        Text.concat [ "(", Text.intercalate "|" ordinals, ")" ]+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> HashMap.lookup (Text.toLower match) ordinalsHashMap+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+) ?('?)(inci|nci|\x0131nc\x0131|nc\x0131|uncu|ncu|\x00fcnc\x00fc|nc\x00fc|.)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  , ruleOrdinalsFirstst+  ]
+ Duckling/Ordinal/Types.hs view
@@ -0,0 +1,40 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Ordinal.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Text (Text)+import GHC.Generics+import Prelude++import Duckling.Resolve (Resolve(..))++newtype OrdinalData = OrdinalData { value :: Int }+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++instance Resolve OrdinalData where+  type ResolvedValue OrdinalData = OrdinalData+  resolve _ x = Just x++instance ToJSON OrdinalData where+  toJSON (OrdinalData value) = object+    [ "type" .= ("value" :: Text)+    , "value" .= value+    ]++isBetween :: Ord a => a -> a -> a -> Bool+isBetween x low high = low <= x && x <= high
+ Duckling/Ordinal/UK/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.UK.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = UK}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "перший"+             , "перша"+             , "перше"+             , "1а"+             , "1-а"+             , "1ий"+             , "1-ий"+             , "1е"+             , "1-е"+             ]+  , examples (OrdinalData 4)+             [ "четвертий"+             , "четверта"+             , "четверте"+             , "4ий"+             , "4а"+             , "4е"+             , "4-ий"+             , "4-а"+             , "4-е"+             ]+  , examples (OrdinalData 15)+             [ "п‘ятнадцятий"+             , "15й"+             , "15-й"+             ]+  , examples (OrdinalData 21)+             [ "21й"+             , "21-й"+             , "двадцять перший"+             ]+  , examples (OrdinalData 31)+             [ "31ий"+             , "31-ий"+             , "тридцять перший"+             ]+  , examples (OrdinalData 48)+             [ "48е"+             , "48-е"+             , "сорок восьме"+             ]+  , examples (OrdinalData 99)+             [ "99ий"+             , "99-й"+             , "дев‘яносто дев‘ятий"+             ]+  ]
+ Duckling/Ordinal/UK/Rules.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 GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ordinal.UK.Rules+  ( rules ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Control.Monad (join)+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Helpers+import Duckling.Regex.Types+import Duckling.Types++ordinalsFirstThMap :: HashMap Text Int+ordinalsFirstThMap = HashMap.fromList+  [ ( "\x043f\x0435\x0440\x0448"                   , 1 )+  , ( "\x0434\x0440\x0443\x0433"                   , 2 )+  , ( "\x0442\x0440\x0435\x0442"                   , 3 )+  , ( "\x0447\x0435\x0442\x0432\x0435\x0440\x0442" , 4 )+  , ( "\x043f\x2018\x044f\x0442"                   , 5 )+  , ( "\x0448\x043e\x0441\x0442"                   , 6 )+  , ( "\x0441\x044c\x043e\x043c"                   , 7 )+  , ( "\x0432\x043e\x0441\x044c\x043c"             , 8 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x0442"       , 9 )+  , ( "\x0434\x0435\x0441\x044f\x0442"             , 10 )+  , ( "\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x044f\x0442"             , 11 )+  , ( "\x0434\x0432\x0430\x043d\x0430\x0434\x0446\x044f\x0442"             , 12 )+  , ( "\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x044f\x0442"             , 13 )+  , ( "\x0447\x043e\x0442\x0438\x0440\x043d\x0430\x0434\x0446\x044f\x0442" , 14 )+  , ( "\x043f\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442"       , 15 )+  , ( "\x0448\x0456\x0441\x0442\x043d\x0430\x0434\x0446\x044f\x0442"       , 16 )+  , ( "\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442"             , 17 )+  , ( "\x0432\x0456\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442" , 18 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442" , 19 )+  , ( "\x0434\x0432\x0430\x0434\x0446\x044f\x0442"                               , 20 )+  ]++ruleOrdinalsFirstth :: Rule+ruleOrdinalsFirstth = Rule+  { name = "ordinals (first..19th)"+  , pattern =+    [ regex "(\x043f\x0435\x0440\x0448|\x0434\x0440\x0443\x0433|\x0442\x0440\x0435\x0442|\x0447\x0435\x0442\x0432\x0435\x0440\x0442|\x043f\x2018\x044f\x0442|\x0448\x043e\x0441\x0442|\x0441\x044c\x043e\x043c|\x0432\x043e\x0441\x044c\x043c|\x0434\x0435\x0432\x2018\x044f\x0442|\x0434\x0435\x0441\x044f\x0442|\x043e\x0434\x0438\x043d\x0430\x0434\x0446\x044f\x0442|\x0434\x0432\x0430\x043d\x0430\x0434\x0446\x044f\x0442|\x0442\x0440\x0438\x043d\x0430\x0434\x0446\x044f\x0442|\x0447\x043e\x0442\x0438\x0440\x043d\x0430\x0434\x0446\x044f\x0442|\x043f\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442|\x0448\x0456\x0441\x0442\x043d\x0430\x0434\x0446\x044f\x0442|\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442|\x0432\x0456\x0441\x0456\x043c\x043d\x0430\x0434\x0446\x044f\x0442|\x0434\x0435\x0432\x2018\x044f\x0442\x043d\x0430\x0434\x0446\x044f\x0442|\x0434\x0432\x0430\x0434\x0446\x044f\x0442)(\x0438\x0439|\x0456\x0439|\x0430|\x044f|\x0435|\x0454)"+    ]+  , prod = \tokens -> case tokens of+    (Token RegexMatch (GroupMatch (match:_)):_) ->+      ordinal <$> HashMap.lookup (Text.toLower match) ordinalsFirstThMap+    _ -> Nothing+  }++ordinalTensMap :: HashMap Text Int+ordinalTensMap = HashMap.fromList+  [ ( "\x0434\x0432\x0430\x0434\x0446\x044f\x0442\x044c"             , 20 )+  , ( "\x0442\x0440\x0438\x0434\x0446\x044f\x0442\x044c"             , 30 )+  , ( "\x0441\x043e\x0440\x043e\x043a"                               , 40 )+  , ( "\x043f\x2018\x044f\x0442\x0434\x0435\x0441\x044f\x0442"       , 50 )+  , ( "\x0448\x0456\x0441\x0442\x0434\x0435\x0441\x044f\x0442"       , 60 )+  , ( "\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442"             , 70 )+  , ( "\x0432\x0456\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442" , 80 )+  , ( "\x0434\x0435\x0432\x2018\x044f\x043d\x043e\x0441\x0442\x043e" , 90 )+  ]++ruleOrdinal :: Rule+ruleOrdinal = Rule+  { name = "ordinal 21..99"+  , pattern =+    [ regex "(\x0434\x0432\x0430\x0434\x0446\x044f\x0442\x044c|\x0442\x0440\x0438\x0434\x0446\x044f\x0442\x044c|\x0441\x043e\x0440\x043e\x043a|\x043f\x2018\x044f\x0442\x0434\x0435\x0441\x044f\x0442|\x0448\x0456\x0441\x0442\x044c\x0434\x0435\x0441\x044f\x0442|\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442|\x0432\x0456\x0441\x0456\x043c\x0434\x0435\x0441\x044f\x0442|\x0434\x0435\x0432\x2018\x044f\x043d\x043e\x0441\x0442\x043e)"+    , regex "(\x043f\x0435\x0440\x0448|\x0434\x0440\x0443\x0433|\x0442\x0440\x0435\x0442|\x0447\x0435\x0442\x0432\x0435\x0440\x0442|\x043f\x2018\x044f\x0442|\x0448\x043e\x0441\x0442|\x0441\x044c\x043e\x043c|\x0432\x043e\x0441\x044c\x043c|\x0434\x0435\x0432\x2018\x044f\x0442)(\x0438\x0439|\x0456\x0439|\x0430|\x044f|\x0435|\x0454)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+        v1 <- HashMap.lookup (Text.toLower m1) ordinalTensMap+        v2 <- HashMap.lookup (Text.toLower m2) ordinalsFirstThMap -- map to 1..9+        Just . ordinal $ v1 + v2+      _ -> Nothing+  }++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "0*(\\d+)-?((\x0438|\x0456)?\x0439|\x0430|\x044f|\x0435|\x0454)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> ordinal <$> parseInt match+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinal+  , ruleOrdinalDigits+  , ruleOrdinalsFirstth+  ]
+ Duckling/Ordinal/VI/Corpus.hs view
@@ -0,0 +1,31 @@+-- 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.Ordinal.VI.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = VI}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 1)+             [ "đầu tiên"+             , "thứ nhất"+             , "thứ 1"+             ]+  ]
+ Duckling/Ordinal/VI/Rules.hs view
@@ -0,0 +1,33 @@+-- 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 #-}++module Duckling.Ordinal.VI.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Ordinal.Helpers+import Duckling.Types++ruleOrdinals :: Rule+ruleOrdinals = Rule+  { name = "ordinals"+  , pattern =+    [ regex "(\x0111\x1ea7u ti\x00ean|th\x1ee9 nh\x1ea5t|th\x1ee9 1)"+    ]+  , prod = \_ -> Just $ ordinal 1+  }++rules :: [Rule]+rules =+  [ ruleOrdinals+  ]
+ Duckling/Ordinal/ZH/Corpus.hs view
@@ -0,0 +1,36 @@+-- 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.Ordinal.ZH.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Ordinal.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ZH}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (OrdinalData 7)+             [ "第七"+             ]+  , examples (OrdinalData 11)+             [ "第十一"+             ]+  , examples (OrdinalData 91)+             [ "第九十一"+             ]+  ]
+ Duckling/Ordinal/ZH/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.Ordinal.ZH.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Ordinal.Helpers+import Duckling.Types++ruleOrdinalDigits :: Rule+ruleOrdinalDigits = Rule+  { name = "ordinal (digits)"+  , pattern =+    [ regex "\x7b2c"+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = x}):_) ->+        Just . ordinal $ floor x+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleOrdinalDigits+  ]
+ Duckling/PhoneNumber/Corpus.hs view
@@ -0,0 +1,76 @@+-- 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.PhoneNumber.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.PhoneNumber.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext, examples)+  where+    examples =+      [ "12345"+      , "1234567890123456777777"+      , "12345678901234567"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (PhoneNumberValue "6507018887")+             [ "650-701-8887"+             ]+  , examples (PhoneNumberValue "(+1) 6507018887")+             [ "(+1)650-701-8887"+             , "(+1)   650 - 701  8887"+             , "(+1) 650-701-8887"+             , "+1 6507018887"+             ]+  , examples (PhoneNumberValue "(+33) 146647998")+             [ "+33 1 46647998"+             ]+  , examples (PhoneNumberValue "0620702220")+             [ "06 2070 2220"+             ]+  , examples (PhoneNumberValue "6507018887 ext 897")+             [ "(650)-701-8887 ext 897"+             ]+  , examples (PhoneNumberValue "(+1) 2025550121")+             [ "+1-202-555-0121"+             , "+1 202.555.0121"+             ]+  , examples (PhoneNumberValue "4866827")+             [ "4.8.6.6.8.2.7"+             ]+  , examples (PhoneNumberValue "06354640807")+             [ "06354640807"+             ]+  , examples (PhoneNumberValue "18998078030")+             [ "18998078030"+             ]+  , examples (PhoneNumberValue "61992852776")+             [ "61 - 9 9285-2776"+             ]+  , examples (PhoneNumberValue "19997424919")+             [ "(19) 997424919"+             ]+  , examples (PhoneNumberValue "(+55) 19992842606")+             [ "+55 19992842606"+             ]+  ]
+ Duckling/PhoneNumber/PT/Corpus.hs view
@@ -0,0 +1,31 @@+-- 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.PhoneNumber.PT.Corpus+  ( corpus+  ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.PhoneNumber.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (PhoneNumberValue "6502834757 ext 897")+             [ "(650)-283-4757 ramal 897"+             ]+  ]
+ Duckling/PhoneNumber/PT/Rules.hs view
@@ -0,0 +1,56 @@+-- 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 #-}++module Duckling.PhoneNumber.PT.Rules+  ( rules ) where++import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.PhoneNumber.Types (PhoneNumberData(..))+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.PhoneNumber.Types as TPhoneNumber++rulePhoneNumber :: Rule+rulePhoneNumber = Rule+  { name = "phone number"+  , pattern =+    -- We somewhat arbitrarly use 20 here to limit the length of matches,+    -- otherwise due to backtracking the regexp will take very long time+    -- or run out of stack for some inputs.+    [ regex $+        "(?:\\(?\\+(\\d{1,2})\\)?[\\s-\\.]*)?" ++ -- area code+        "((?=[-\\d()\\s\\.]{6,16}(?:\\s*ramal\\.?\\s*(?:\\d{1,20}))?(?:[^\\d]+|$))(?:[\\d(]{1,20}(?:[-)\\s\\.]*\\d{1,20}){0,20}){1,20})" ++ -- nums+        "(?:\\s*ramal\\.?\\s*(\\d{1,20}))?" -- extension+    ]+  , prod = \xs -> case xs of+      (Token RegexMatch (GroupMatch (code:nums:ext:_)):_) ->+        let parseNum x = toInteger <$> parseInt x+            mcode = parseNum code+            mext = parseNum ext+            cleanup = Text.filter (not . isWhitespace)+            isWhitespace x = elem x ['.', ' ', '-', '\t', '(', ')']+        in Just . Token PhoneNumber $ PhoneNumberData+          { TPhoneNumber.prefix = mcode+          , TPhoneNumber.number = cleanup nums+          , TPhoneNumber.extension = mext+          }+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ rulePhoneNumber+  ]
+ Duckling/PhoneNumber/Rules.hs view
@@ -0,0 +1,54 @@+-- 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 #-}++module Duckling.PhoneNumber.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.PhoneNumber.Types (PhoneNumberData(..))+import qualified Duckling.PhoneNumber.Types as TPhoneNumber+import Duckling.Regex.Types+import Duckling.Types++rulePhoneNumber :: Rule+rulePhoneNumber = Rule+  { name = "phone number"+  , pattern =+    -- We somewhat arbitrarly use 20 here to limit the length of matches,+    -- otherwise due to backtracking the regexp will take very long time+    -- or run out of stack for some inputs.+    [ regex $+        "(?:\\(?\\+(\\d{1,2})\\)?[\\s-\\.]*)?" ++ -- area code+        "((?=[-\\d()\\s\\.]{6,16}(?:\\s*e?xt?\\.?\\s*(?:\\d{1,20}))?(?:[^\\d]+|$))(?:[\\d(]{1,20}(?:[-)\\s\\.]*\\d{1,20}){0,20}){1,20})" ++ -- nums+        "(?:\\s*e?xt?\\.?\\s*(\\d{1,20}))?" -- extension+    ]+  , prod = \xs -> case xs of+      (Token RegexMatch (GroupMatch (code:nums:ext:_)):_) ->+        let parseNum x = toInteger <$> parseInt x+            mcode = parseNum code+            mext = parseNum ext+            cleanup = Text.filter (not . isWhitespace)+            isWhitespace x = elem x ['.', ' ', '-', '\t', '(', ')']+        in Just . Token PhoneNumber $ PhoneNumberData+          { TPhoneNumber.prefix = mcode+          , TPhoneNumber.number = cleanup nums+          , TPhoneNumber.extension = mext+          }+      _ -> Nothing+  }++rules :: [Rule]+rules = [ rulePhoneNumber ]
+ Duckling/PhoneNumber/Types.hs view
@@ -0,0 +1,54 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.PhoneNumber.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as Text+import GHC.Generics+import qualified TextShow as TS++import Prelude++import Duckling.Resolve (Resolve(..))++data PhoneNumberData = PhoneNumberData+  { prefix :: Maybe Integer+  , number :: Text+  , extension :: Maybe Integer+  }+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve PhoneNumberData where+  type ResolvedValue PhoneNumberData = PhoneNumberValue+  resolve _ PhoneNumberData {prefix, number, extension} = Just PhoneNumberValue+    {value = Text.concat [p, number, e]}+    where+      p = case prefix of+        Just p -> "(+" <> TS.showt p <> ") "+        Nothing -> ""+      e = case extension of+        Just e -> " ext " <> TS.showt e+        Nothing -> ""++data PhoneNumberValue = PhoneNumberValue { value :: Text }+  deriving (Eq, Ord, Show)++instance ToJSON PhoneNumberValue where+  toJSON (PhoneNumberValue value) = object [ "value" .= value ]
+ Duckling/Quantity/EN/Corpus.hs view
@@ -0,0 +1,34 @@+-- 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.Quantity.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Quantity.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData Pound 2 (Just "meat"))+             [ "two pounds of meat"+             ]+  , examples (QuantityData Pound 1 Nothing)+             [ "a Pound"+             ]+  , examples (QuantityData Cup 3 (Just "sugar"))+             [ "3 Cups of sugar"+             ]+  ]
+ Duckling/Quantity/EN/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.EN.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Quantity.Helpers+import qualified Duckling.Quantity.Types as TQuantity+import Duckling.Regex.Types+import Duckling.Dimensions.Types+import Duckling.Types++ruleNumeralQuantity :: Rule+ruleNumeralQuantity = Rule+  { name = "<number> <quantity>"+  , pattern =+    [ dimension Numeral+    , regex "(pound|cup)s?"+    ]+  , prod = \tokens -> case tokens of+    (Token Numeral nd:+     Token RegexMatch (GroupMatch (match:_)):+     _) -> case Text.toLower match of+      "cup"    -> Just . Token Quantity . quantity TQuantity.Cup $ TNumeral.value nd+      "cups"   -> Just . Token Quantity . quantity TQuantity.Cup $ TNumeral.value nd+      "pound"  -> Just . Token Quantity . quantity TQuantity.Pound $ TNumeral.value nd+      "pounds" -> Just . Token Quantity . quantity TQuantity.Pound $ TNumeral.value nd+      _ -> Nothing+    _ -> Nothing+  }++ruleAQuantity :: Rule+ruleAQuantity = Rule+  { name = "a quantity"+  , pattern = [ regex "a (pound|cup)s?"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of+        "cup"    -> Just . Token Quantity $ quantity TQuantity.Cup 1+        "cups"   -> Just . Token Quantity $ quantity TQuantity.Cup 1+        "pound"  -> Just . Token Quantity $ quantity TQuantity.Pound 1+        "pounds" -> Just . Token Quantity $ quantity TQuantity.Pound 1+        _        -> Nothing+      _ -> Nothing+  }++ruleQuantityOfProduct :: Rule+ruleQuantityOfProduct = Rule+  { name = "<quantity> of product"+  , pattern =+    [ dimension Quantity+    , regex "of (meat|sugar)"+    ]+  , prod = \tokens -> case tokens of+    (Token Quantity qd:Token RegexMatch (GroupMatch (product:_)):_) ->+      Just . Token Quantity $ withProduct product qd+    _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralQuantity+  , ruleAQuantity+  , ruleQuantityOfProduct+  ]
+ Duckling/Quantity/FR/Corpus.hs view
@@ -0,0 +1,36 @@+-- 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.Quantity.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Quantity.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData Cup 2 (Just "café"))+             [ "2 tasses de café"+             ]+  , examples (QuantityData Cup 1 Nothing)+             [ "une Tasse"+             ]+  , examples (QuantityData Tablespoon 3 (Just "sucre"))+             [ "3 Cuillères à soupe de sucre"+             ]+  ]
+ Duckling/Quantity/FR/Rules.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.FR.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Quantity.Helpers+import qualified Duckling.Quantity.Types as TQuantity+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Regex.Types+import Duckling.Types++ruleNumeralUnits :: Rule+ruleNumeralUnits = Rule+  { name = "<number> <units>"+  , pattern =+    [ dimension Numeral+    , regex "(tasses?|cuill?(e|\x00e8)res? (a|\x00e0) soupe?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "tasse"  -> Just . Token Quantity $ quantity TQuantity.Cup v+         "tasses" -> Just . Token Quantity $ quantity TQuantity.Cup v+         _        -> Just . Token Quantity $ quantity TQuantity.Tablespoon v+      _ -> Nothing+  }++ruleQuantityOfProduct :: Rule+ruleQuantityOfProduct = Rule+  { name = "<quantity> of product"+  , pattern =+    [ dimension Quantity+    , regex "de (caf(e|\x00e9)|sucre)"+    ]+  , prod = \tokens -> case tokens of+      (Token Quantity qd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> Just . Token Quantity $ withProduct match qd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralUnits+  , ruleQuantityOfProduct+  ]
+ Duckling/Quantity/HR/Corpus.hs view
@@ -0,0 +1,33 @@+-- 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.Quantity.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Quantity.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData Gram 2000 (Just "meso"))+             [ "dvije kile mesa"+             , "dva kilograma mesa"+             ]+  , examples (QuantityData Gram 1000 Nothing)+             [ "1 kilograma"+             ]+  ]
+ Duckling/Quantity/HR/Rules.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.HR.Rules+  ( rules ) where++import Data.String+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Quantity.Helpers+import Duckling.Regex.Types+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.Quantity.Types as TQuantity++ruleNumberUnits :: Rule+ruleNumberUnits = Rule+  { name = "<number> <units>"+  , pattern =+    [ dimension Numeral+    , regex "k(il(o|e|a))?(g(rama?)?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:_) ->+        Just . Token Quantity $ quantity TQuantity.Gram (1000 * v)+      _ -> Nothing+  }++ruleQuantityProduct :: Rule+ruleQuantityProduct = Rule+  { name = "<quantity> product"+  , pattern =+    [ dimension Quantity+    , regex "(mes(o|a)|soli?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Quantity qd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "meso" -> Just . Token Quantity $ withProduct "meso" qd+         "mesa" -> Just . Token Quantity $ withProduct "meso" qd+         "sol" -> Just . Token Quantity $ withProduct "sol" qd+         "soli" -> Just . Token Quantity $ withProduct "sol" qd+         _      -> Nothing+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumberUnits+  , ruleQuantityProduct+  ]
+ Duckling/Quantity/Helpers.hs view
@@ -0,0 +1,31 @@+-- 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.Quantity.Helpers+  ( quantity+  , withProduct+  ) where++import Data.Text (Text)+import Prelude++import Duckling.Quantity.Types (QuantityData(..))+import qualified Duckling.Quantity.Types as TQuantity++-- -----------------------------------------------------------------+-- Patterns++-- -----------------------------------------------------------------+-- Production++quantity :: TQuantity.Unit -> Double -> QuantityData+quantity u x = QuantityData+  {TQuantity.unit = u, TQuantity.value = x, TQuantity.product = Nothing}++withProduct :: Text -> QuantityData -> QuantityData+withProduct value qd = qd {TQuantity.product = Just value}
+ Duckling/Quantity/KO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Quantity.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData (Custom "근") 2 (Just "삼겹살"))+             [ "삼겹살 두근"+             ]+  , examples (QuantityData (Custom "근") 1 Nothing)+             [ "한근"+             ]+  , examples (QuantityData Gram 600 Nothing)+             [ "육백그람"+             ]+  , examples (QuantityData Cup 3 (Just "콜라"))+             [ "콜라 세컵"+             ]+  ]
+ Duckling/Quantity/KO/Rules.hs view
@@ -0,0 +1,84 @@+-- 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 #-}++module Duckling.Quantity.KO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Quantity.Helpers+import qualified Duckling.Quantity.Types as TQuantity+import Duckling.Regex.Types+import Duckling.Types++ruleQuantityOfProduct :: Rule+ruleQuantityOfProduct = Rule+  { name = "<quantity> of product"+  , pattern =+    [ dimension Quantity+    , regex "\xc758 (\xc0bc\xacb9\xc0b4|\xcf5c\xb77c)"+    ]+  , prod = \tokens -> case tokens of+      (Token Quantity qd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> Just . Token Quantity $ withProduct match qd+      _ -> Nothing+  }++ruleQuantityOfProduct2 :: Rule+ruleQuantityOfProduct2 = Rule+  { name = "<quantity> of product"+  , pattern =+    [ regex "(\xc0bc\xacb9\xc0b4|\xcf5c\xb77c)"+    , dimension Quantity+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       Token Quantity qd:+       _) -> Just . Token Quantity $ withProduct match qd+      _ -> Nothing+  }++ruleNumeralUnits :: Rule+ruleNumeralUnits = Rule+  { name = "<number> <units>"+  , pattern =+    [ dimension Numeral+    , regex "(\xac1c|\xd310|\xadf8(\xb7a8|\xb78c)|\xadfc|\xd30c\xc6b4(\xb4dc|\xc988)|\xc8111\xc2dc|\xadf8\xb987|\xcef5)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case match of+         "\xac1c"             -> Just . Token Quantity $ quantity TQuantity.Unnamed v+         "\xd310"             -> Just . Token Quantity $ quantity (TQuantity.Custom "판") v+         "\xadfc"             -> Just . Token Quantity $ quantity (TQuantity.Custom "근") v+         "\xadf8\xb7a8"       -> Just . Token Quantity $ quantity TQuantity.Gram v+         "\xadf8\xb78c"       -> Just . Token Quantity $ quantity TQuantity.Gram v+         "\xd30c\xc6b4\xb4dc" -> Just . Token Quantity $ quantity TQuantity.Pound v+         "\xd30c\xc6b4\xc988" -> Just . Token Quantity $ quantity TQuantity.Pound v+         "\xc8111\xc2dc"      -> Just . Token Quantity $ quantity TQuantity.Dish v+         "\xadf8\xb987"       -> Just . Token Quantity $ quantity TQuantity.Bowl v+         "\xcef5"             -> Just . Token Quantity $ quantity TQuantity.Cup v+         _                    -> Nothing+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralUnits+  , ruleQuantityOfProduct+  , ruleQuantityOfProduct2+  ]
+ Duckling/Quantity/PT/Corpus.hs view
@@ -0,0 +1,36 @@+-- 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.Quantity.PT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Quantity.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData Cup 2 (Just "café"))+             [ "2 copos de café"+             ]+  , examples (QuantityData Cup 1 Nothing)+             [ "um Copo"+             ]+  , examples (QuantityData Pound 100 (Just "acucar"))+             [ "100 Libras de acucar"+             ]+  ]
+ Duckling/Quantity/PT/Rules.hs view
@@ -0,0 +1,62 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.PT.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Quantity.Helpers+import qualified Duckling.Quantity.Types as TQuantity+import Duckling.Regex.Types+import Duckling.Types++ruleNumeralUnits :: Rule+ruleNumeralUnits = Rule+  { name = "<number> <units>"+  , pattern =+    [ dimension Numeral+    , regex "(libra|copo)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+         "copo"   -> Just . Token Quantity $ quantity TQuantity.Cup v+         "libra"  -> Just . Token Quantity $ quantity TQuantity.Pound v+         _        -> Nothing+      _ -> Nothing+  }++ruleQuantityOfProduct :: Rule+ruleQuantityOfProduct = Rule+  { name = "<quantity> of product"+  , pattern =+    [ dimension Quantity+    , regex "de (caf(e|\x00e9)|a(\x00e7|c)ucar)"+    ]+  , prod = \tokens -> case tokens of+      (Token Quantity qd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> Just . Token Quantity $ withProduct match qd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralUnits+  , ruleQuantityOfProduct+  ]
+ Duckling/Quantity/RO/Corpus.hs view
@@ -0,0 +1,36 @@+-- 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.Quantity.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Quantity.Types+import Duckling.Resolve+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (QuantityData Pound 2 (Just "carne"))+             [ "doua livre de carne"+             ]+  , examples (QuantityData Pound 1 Nothing)+             [ "o livră"+             ]+  , examples (QuantityData Pound 500 (Just "zahăr"))+             [ "cinci sute livre de zahăr"+             ]+  ]
+ Duckling/Quantity/RO/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Quantity.RO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Quantity.Helpers+import qualified Duckling.Quantity.Types as TQuantity+import Duckling.Regex.Types+import Duckling.Types++ruleNumeralUnits :: Rule+ruleNumeralUnits = Rule+  { name = "<number> <units>"+  , pattern =+    [ dimension Numeral+    , regex "livr(a|e|\x0103)"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral NumeralData {TNumeral.value = v}:_) ->+        Just . Token Quantity $ quantity TQuantity.Pound v+      _ -> Nothing+  }++ruleQuantityOfProduct :: Rule+ruleQuantityOfProduct = Rule+  { name = "<quantity> of product"+  , pattern =+    [ dimension Quantity+    , regex "de (carne|can(a|\x0103)|zah(a|\x0103)r)"+    ]+  , prod = \tokens -> case tokens of+      (Token Quantity qd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> Just . Token Quantity $ withProduct match qd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralUnits+  , ruleQuantityOfProduct+  ]
+ Duckling/Quantity/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Quantity.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 Unit+  = Bowl+  | Cup+  | Custom Text+  | Dish+  | Gram+  | Pint+  | Pound+  | Quart+  | Tablespoon+  | Teaspoon+  | Unnamed+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance ToJSON Unit where+  toJSON (Custom x) = String $ Text.toLower x+  toJSON x = String . Text.toLower . Text.pack $ show x++data QuantityData = QuantityData+  { unit :: Unit+  , value :: Double+  , product :: Maybe Text+  } deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance ToJSON QuantityData where+  toJSON (QuantityData unit value product) = object $+    [ "type" .= ("value" :: Text)+    , "value" .= value+    , "unit" .= unit+    ]+    ++ [ "product" .= p | Just p <- [product] ]++instance Resolve QuantityData where+  type ResolvedValue QuantityData = QuantityData+  resolve _ x = Just x
+ Duckling/Ranking/Classifiers.hs view
@@ -0,0 +1,68 @@+-- 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.Ranking.Classifiers+  ( classifiers+  ) where++import Duckling.Lang+import qualified Duckling.Ranking.Classifiers.AR as ARClassifiers+import qualified Duckling.Ranking.Classifiers.DA as DAClassifiers+import qualified Duckling.Ranking.Classifiers.DE as DEClassifiers+import qualified Duckling.Ranking.Classifiers.EN as ENClassifiers+import qualified Duckling.Ranking.Classifiers.ES as ESClassifiers+import qualified Duckling.Ranking.Classifiers.ET as ETClassifiers+import qualified Duckling.Ranking.Classifiers.FR as FRClassifiers+import qualified Duckling.Ranking.Classifiers.GA as GAClassifiers+import qualified Duckling.Ranking.Classifiers.HE as HEClassifiers+import qualified Duckling.Ranking.Classifiers.HR as HRClassifiers+import qualified Duckling.Ranking.Classifiers.ID as IDClassifiers+import qualified Duckling.Ranking.Classifiers.IT as ITClassifiers+import qualified Duckling.Ranking.Classifiers.JA as JAClassifiers+import qualified Duckling.Ranking.Classifiers.KO as KOClassifiers+import qualified Duckling.Ranking.Classifiers.MY as MYClassifiers+import qualified Duckling.Ranking.Classifiers.NB as NBClassifiers+import qualified Duckling.Ranking.Classifiers.NL as NLClassifiers+import qualified Duckling.Ranking.Classifiers.PL as PLClassifiers+import qualified Duckling.Ranking.Classifiers.PT as PTClassifiers+import qualified Duckling.Ranking.Classifiers.RO as ROClassifiers+import qualified Duckling.Ranking.Classifiers.RU as RUClassifiers+import qualified Duckling.Ranking.Classifiers.SV as SVClassifiers+import qualified Duckling.Ranking.Classifiers.TR as TRClassifiers+import qualified Duckling.Ranking.Classifiers.UK as UKClassifiers+import qualified Duckling.Ranking.Classifiers.VI as VIClassifiers+import qualified Duckling.Ranking.Classifiers.ZH as ZHClassifiers+import Duckling.Ranking.Types++classifiers :: Lang -> Classifiers+classifiers AR = ARClassifiers.classifiers+classifiers DA = DAClassifiers.classifiers+classifiers DE = DEClassifiers.classifiers+classifiers EN = ENClassifiers.classifiers+classifiers ES = ESClassifiers.classifiers+classifiers ET = ETClassifiers.classifiers+classifiers FR = FRClassifiers.classifiers+classifiers GA = GAClassifiers.classifiers+classifiers HE = HEClassifiers.classifiers+classifiers HR = HRClassifiers.classifiers+classifiers ID = IDClassifiers.classifiers+classifiers IT = ITClassifiers.classifiers+classifiers JA = JAClassifiers.classifiers+classifiers KO = KOClassifiers.classifiers+classifiers MY = MYClassifiers.classifiers+classifiers NB = NBClassifiers.classifiers+classifiers NL = NLClassifiers.classifiers+classifiers PL = PLClassifiers.classifiers+classifiers PT = PTClassifiers.classifiers+classifiers RO = ROClassifiers.classifiers+classifiers RU = RUClassifiers.classifiers+classifiers SV = SVClassifiers.classifiers+classifiers TR = TRClassifiers.classifiers+classifiers UK = UKClassifiers.classifiers+classifiers VI = VIClassifiers.classifiers+classifiers ZH = ZHClassifiers.classifiers
+ Duckling/Ranking/Classifiers/AR.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.AR (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/DA.hs view
@@ -0,0 +1,1566 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.DA (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.2039728043259361),+                                    ("hh:mm", -1.6094379124341003), ("hour", -1.6094379124341003),+                                    ("minute", -1.2039728043259361)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.778087857209029, unseen = -4.962844630259907,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 141},+                   koData =+                     ClassData{prior = -0.6148599592306538, unseen = -5.123963979403259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 166}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.0986122886681098),+                                    ("tomorrowevening", -2.0149030205422647),+                                    ("named-daymorning", -2.0149030205422647),+                                    ("tomorrowlunch", -2.0149030205422647),+                                    ("yesterdayevening", -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -1.1786549963416462),+                                    ("year (latent)in|during the <part-of-day>",+                                     -1.1786549963416462)],+                               n = 3}}),+       ("dd/mm",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.25593337413720063,+                               unseen = -4.6443908991413725,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> timezone", -3.536116699561526),+                                    ("time-of-day (latent)", -1.2007417837444896),+                                    ("relative minutes after|past <integer> (hour-of-day)",+                                     -3.536116699561526),+                                    ("hh:mm", -2.069779630768099),+                                    ("<time-of-day> sharp", -3.536116699561526),+                                    ("hour", -1.1382214267631554), ("minute", -1.8015156441734197)],+                               n = 48},+                   koData =+                     ClassData{prior = -1.488077055429833, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.8472978603872037),+                                    ("hour", -0.8472978603872037)],+                               n = 14}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList+                                   [("the <day-of-month> (non ordinal)", -2.6149597780361984),+                                    ("<day-of-month>(ordinal) <named-month>", -1.7676619176489945),+                                    ("day", -0.7691330875378672),+                                    ("the <day-of-month> (ordinal)", -3.0204248861443626),+                                    ("named-day", -1.410986973710262)],+                               n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -3.7376696182833684,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 40},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.9808292530117262),+                                    ("hh:mmhh:mm", -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 2}}),+       ("between <datetime> and <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("hh:mmhh:mm", -1.0986122886681098)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.2992829841302609),+                                    ("minuteminute", -1.7047480922384253),+                                    ("minutehour", -1.2992829841302609),+                                    ("hh:mmintersect", -1.7047480922384253)],+                               n = 3}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> more <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)minute (grain)", -1.252762968495368),+                                    ("integer (0..19)minute (grain)", -1.252762968495368),+                                    ("minute", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -2.3025850929940455,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037),+                                    ("ordinals (first..31st)quarter (grain)", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037),+                                    ("ordinals (first..31st)quarter (grain)", -1.252762968495368)],+                               n = 2}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.46117571512217015, unseen = -5.8111409929767,+                               likelihoods =+                                 HashMap.fromList+                                   [("<datetime> - <datetime> (interval)on <date>",+                                     -4.0163830207523885),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.0163830207523885),+                                    ("hourday", -5.1149953094204985),+                                    ("dayhour", -2.863703510814003),+                                    ("daymonth", -3.3232358401924436),+                                    ("monthyear", -3.0355537677406628),+                                    ("intersecthh:mm", -5.1149953094204985),+                                    ("the <day-of-month> (ordinal)named-month",+                                     -3.8622323409251305),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -4.709530201312334),+                                    ("last <day-of-week> of <time>year", -4.709530201312334),+                                    ("todayat <time-of-day>", -4.709530201312334),+                                    ("dayday", -3.0355537677406628),+                                    ("dd/mmat <time-of-day>", -4.198704577546343),+                                    ("intersect by \",\"hh:mm", -4.198704577546343),+                                    ("intersectnamed-month", -5.1149953094204985),+                                    ("dayyear", -3.243193132518907),+                                    ("named-daythis <time>", -3.6109179126442243),+                                    ("tomorrow<time-of-day> sharp", -4.709530201312334),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -4.709530201312334),+                                    ("named-day<time> timezone", -4.421848128860553),+                                    ("named-monthyear", -3.0355537677406628),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.0163830207523885),+                                    ("tomorrowuntil <time-of-day>", -4.709530201312334),+                                    ("absorption of , after named day<day-of-month> (non ordinal) <named-month>",+                                     -4.421848128860553),+                                    ("after <time-of-day>at <time-of-day>", -4.709530201312334),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -4.709530201312334),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -5.1149953094204985),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -5.1149953094204985),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.709530201312334),+                                    ("named-daynext <cycle>", -5.1149953094204985),+                                    ("named-dayintersect", -5.1149953094204985),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.709530201312334),+                                    ("tomorrowafter <time-of-day>", -4.709530201312334),+                                    ("from <time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.198704577546343),+                                    ("dayminute", -2.763620052257021),+                                    ("from <datetime> - <datetime> (interval)on <date>",+                                     -4.421848128860553),+                                    ("<ordinal> <cycle> of <time>year", -4.709530201312334),+                                    ("minuteday", -2.512305623976115),+                                    ("absorption of , after named dayintersect",+                                     -5.1149953094204985),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -5.1149953094204985),+                                    ("named-dayon <date>", -5.1149953094204985),+                                    ("named-dayat <time-of-day>", -4.709530201312334),+                                    ("yearhh:mm", -5.1149953094204985),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -5.1149953094204985),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -4.709530201312334),+                                    ("dd/mmyear", -4.709530201312334),+                                    ("at <time-of-day>on <date>", -5.1149953094204985),+                                    ("between <time-of-day> and <time-of-day> (interval)on <date>",+                                     -5.1149953094204985),+                                    ("between <datetime> and <datetime> (interval)on <date>",+                                     -5.1149953094204985),+                                    ("dayweek", -4.0163830207523885),+                                    ("weekyear", -4.198704577546343),+                                    ("hh:mmtomorrow", -4.421848128860553),+                                    ("tomorrowat <time-of-day>", -3.8622323409251305),+                                    ("named-daythe <day-of-month> (ordinal)", -5.1149953094204985),+                                    ("at <time-of-day>tomorrow", -4.709530201312334),+                                    ("last <cycle> of <time>year", -4.198704577546343),+                                    ("named-daythe <day-of-month> (non ordinal)",+                                     -5.1149953094204985),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -4.709530201312334),+                                    ("yearminute", -5.1149953094204985)],+                               n = 128},+                   koData =+                     ClassData{prior = -0.9957178655054769, unseen = -5.429345628954441,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -4.7318028369214575),+                                    ("dayhour", -3.3455084758015667),+                                    ("daymonth", -2.129113151477074),+                                    ("monthday", -3.8155121050473024),+                                    ("monthyear", -3.8155121050473024),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -3.4790398684260895),+                                    ("named-dayhh:mm", -4.7318028369214575),+                                    ("dd/mmat <time-of-day>", -3.8155121050473024),+                                    ("hourhour", -3.4790398684260895),+                                    ("dayyear", -3.3455084758015667),+                                    ("named-daythis <time>", -2.5917366734251868),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -4.326337728813293),+                                    ("minutemonth", -4.326337728813293),+                                    ("named-monthyear", -3.8155121050473024),+                                    ("in|during the <part-of-day>until <time-of-day>",+                                     -4.326337728813293),+                                    ("absorption of , after named daynamed-month",+                                     -3.6331905482533475),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.326337728813293),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -4.326337728813293),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.7318028369214575),+                                    ("until <time-of-day>on <date>", -4.7318028369214575),+                                    ("dayminute", -3.3455084758015667),+                                    ("minuteday", -3.2277254401451834),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -4.7318028369214575),+                                    ("named-dayat <time-of-day>", -3.8155121050473024),+                                    ("hh:mmon <date>", -3.3455084758015667),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -4.7318028369214575),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -3.8155121050473024),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -3.8155121050473024),+                                    ("this <part-of-day>until <time-of-day>", -4.326337728813293),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -4.326337728813293),+                                    ("tomorrownoon", -4.7318028369214575),+                                    ("this <time>until <time-of-day>", -4.326337728813293),+                                    ("minuteyear", -4.326337728813293),+                                    ("yearminute", -4.326337728813293)],+                               n = 75}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)intersect",+                                     -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)named-month",+                                     -1.7346010553881064),+                                    ("weekmonth", -1.2237754316221157),+                                    ("ordinals (first..31st)day (grain)named-month",+                                     -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.4350845252893227),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.3513752571634776),+                                    ("hh:mmhh:mm", -1.4350845252893227),+                                    ("hourhour", -2.3513752571634776)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.4418327522790392,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -2.6741486494265287),+                                    ("hh:mmtime-of-day (latent)", -1.7578579175523736),+                                    ("minuteminute", -1.9810014688665833),+                                    ("yearyear", -2.6741486494265287),+                                    ("year (latent)year (latent)", -2.6741486494265287),+                                    ("minutehour", -1.7578579175523736),+                                    ("hh:mmintersect", -1.9810014688665833),+                                    ("year (latent)time-of-day (latent)", -2.6741486494265287)],+                               n = 9}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("month (grain)", -2.3025850929940455),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.6094379124341003),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("month", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.1972245773362196),+                                    ("hh:mmhh:mm", -1.0986122886681098),+                                    ("hourhour", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 5}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.4462871026284195),+                                    ("integer (0..19)", -1.0216512475319814)],+                               n = 23}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)quarter (grain)year",+                                     -1.252762968495368),+                                    ("quarteryear", -0.8472978603872037),+                                    ("ordinal (digits)quarter (grain)year", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> after <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (grain)christmas eve", -0.6931471805599453),+                                    ("yearday", -0.6931471805599453)],+                               n = 2}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a pair",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7472144018302211),+                                    ("ordinals (first..31st)named-dayintersect",+                                     -0.9985288301111273),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -1.845826690498331)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7621400520468967),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -0.7621400520468967)],+                               n = 6}}),+       ("the <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (first..31st)",+        Classifier{okData =+                     ClassData{prior = -5.406722127027582e-2,+                               unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18},+                   koData =+                     ClassData{prior = -2.9444389791664407,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.189654742026425,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 64},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8472978603872037), ("evening", -1.252762968495368),+                                    ("morning", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7308875085427924),+                                    ("morning", -0.7308875085427924)],+                               n = 12}}),+       ("christmas eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -9.53101798043249e-2,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.749199854809259),+                                    ("ordinal (digits)named-month", -1.0560526742493137),+                                    ("month", -0.7375989431307791)],+                               n = 10},+                   koData =+                     ClassData{prior = -2.3978952727983707, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -0.916290731874155),+                                    ("month", -0.916290731874155)],+                               n = 1}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.4011973816621555,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 28}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -1.3862943611198906),+                                    ("hour", -0.9808292530117262),+                                    ("evening", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7672551527136672),+                                    ("morning", -0.7672551527136672)],+                               n = 12}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> after <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (grain)christmas eve", -0.6931471805599453),+                                    ("yearday", -0.6931471805599453)],+                               n = 2}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("the <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)", -1.2039728043259361),+                                    ("ordinal (digits)", -0.35667494393873245)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> from now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("second", -1.4469189829363254), ("year", -2.1400661634962708),+                                    ("<integer> <unit-of-duration>", -1.041453874828161),+                                    ("a <unit-of-duration>", -2.1400661634962708),+                                    ("minute", -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5686159179138452),+                                    ("year (grain)", -2.0794415416798357),+                                    ("week (grain)", -1.5686159179138452),+                                    ("day", -2.4849066497880004), ("quarter", -2.4849066497880004),+                                    ("year", -2.0794415416798357),+                                    ("quarter (grain)", -2.4849066497880004),+                                    ("day (grain)", -2.4849066497880004)],+                               n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.6094379124341003),+                                    ("day (grain)", -1.6094379124341003)],+                               n = 1}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.3862943611198906),+                                    ("hour", -1.3862943611198906),+                                    ("<hour-of-day> half (as relative minutes)",+                                     -1.3862943611198906),+                                    ("minute", -1.3862943611198906)],+                               n = 4}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.9711673420999893,+                               unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)", -2.469261259037152e-2)],+                               n = 39},+                   koData =+                     ClassData{prior = -0.475845904869964, unseen = -4.204692619390966,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.29783444391579894),+                                    ("integer (0..19)", -1.3564413979702095)],+                               n = 64}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.1431008436406733, unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 26},+                   koData =+                     ClassData{prior = -2.0149030205422647, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.7621400520468967),+                                    ("named-dayintersect", -1.6094379124341003)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.5408064559779265, unseen = -4.74493212836325,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.538973871058276),+                                    ("integer (0..19)year (grain)", -3.349904087274605),+                                    ("integer (numeric)day (grain)", -2.9444389791664407),+                                    ("integer (0..19)hour (grain)", -4.04305126783455),+                                    ("second", -2.9444389791664407),+                                    ("integer (numeric)second (grain)", -4.04305126783455),+                                    ("a pairhour (grain)", -4.04305126783455),+                                    ("integer (numeric)year (grain)", -3.6375861597263857),+                                    ("day", -2.338303175596125), ("year", -2.9444389791664407),+                                    ("integer (numeric)week (grain)", -3.349904087274605),+                                    ("integer (0..19)month (grain)", -4.04305126783455),+                                    ("integer (0..19)second (grain)", -3.126760535960395),+                                    ("hour", -2.9444389791664407), ("month", -3.6375861597263857),+                                    ("integer (numeric)minute (grain)", -2.790288299339182),+                                    ("integer (0..19)minute (grain)", -2.9444389791664407),+                                    ("integer (numeric)month (grain)", -4.04305126783455),+                                    ("minute", -2.2512917986064953),+                                    ("integer (numeric)hour (grain)", -3.349904087274605),+                                    ("integer (0..19)day (grain)", -2.9444389791664407),+                                    ("integer (0..19)week (grain)", -2.9444389791664407)],+                               n = 46},+                   koData =+                     ClassData{prior = -0.8729402910005413, unseen = -4.48863636973214,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6855773452501515),+                                    ("integer (0..19)year (grain)", -3.378724525810097),+                                    ("integer (numeric)day (grain)", -3.0910424533583156),+                                    ("integer (0..19)hour (grain)", -3.784189633918261),+                                    ("second", -2.867898902044106),+                                    ("integer (numeric)second (grain)", -3.378724525810097),+                                    ("integer (numeric)year (grain)", -3.0910424533583156),+                                    ("day", -2.6855773452501515), ("year", -2.6855773452501515),+                                    ("integer (numeric)week (grain)", -3.378724525810097),+                                    ("integer (0..19)month (grain)", -3.0910424533583156),+                                    ("integer (0..19)second (grain)", -3.378724525810097),+                                    ("hour", -2.6855773452501515), ("month", -2.6855773452501515),+                                    ("integer (numeric)minute (grain)", -3.378724525810097),+                                    ("integer (0..19)minute (grain)", -3.378724525810097),+                                    ("integer (numeric)month (grain)", -3.378724525810097),+                                    ("minute", -2.867898902044106),+                                    ("integer (numeric)hour (grain)", -2.867898902044106),+                                    ("integer (0..19)day (grain)", -3.378724525810097),+                                    ("integer (0..19)week (grain)", -3.0910424533583156)],+                               n = 33}}),+       ("<duration> after <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("a <unit-of-duration>christmas eve", -1.5040773967762742),+                                    ("yearday", -0.8109302162163288),+                                    ("<integer> <unit-of-duration>christmas eve",+                                     -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("integer (numeric)time-of-day (latent)", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.0794415416798357),+                                    ("year (grain)", -2.4849066497880004),+                                    ("second", -2.0794415416798357),+                                    ("week (grain)", -2.0794415416798357),+                                    ("day", -2.4849066497880004),+                                    ("minute (grain)", -2.4849066497880004),+                                    ("year", -2.4849066497880004),+                                    ("second (grain)", -2.0794415416798357),+                                    ("minute", -2.4849066497880004),+                                    ("day (grain)", -2.4849066497880004)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.1590646946296874, unseen = -4.442651256490317,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>named-day", -3.7376696182833684),+                                    ("intersect by \",\"year", -3.7376696182833684),+                                    ("hh:mmintersect by \",\"", -3.7376696182833684),+                                    ("dayday", -2.032921526044943),+                                    ("hh:mmnamed-day", -3.7376696182833684),+                                    ("named-dayintersect by \",\"", -3.332204510175204),+                                    ("dayyear", -2.8213788864092133),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -3.7376696182833684),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -3.332204510175204),+                                    ("<named-month> <day-of-month> (non ordinal)named-day",+                                     -3.7376696182833684),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -3.044522437723423),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.639057329615259),+                                    ("hh:mmintersect", -3.7376696182833684),+                                    ("intersect by \",\"intersect", -3.7376696182833684),+                                    ("named-dayintersect", -3.7376696182833684),+                                    ("at <time-of-day>intersect", -3.7376696182833684),+                                    ("dayminute", -2.639057329615259),+                                    ("intersectyear", -3.7376696182833684),+                                    ("minuteday", -2.032921526044943),+                                    ("hh:mmabsorption of , after named day", -3.7376696182833684),+                                    ("at <time-of-day>intersect by \",\"", -3.7376696182833684),+                                    ("at <time-of-day>absorption of , after named day",+                                     -3.7376696182833684),+                                    ("intersectintersect", -3.7376696182833684),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.332204510175204)],+                               n = 29},+                   koData =+                     ClassData{prior = -1.916922612182061, unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.791759469228055),+                                    ("daymonth", -1.791759469228055)],+                               n = 5}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -1.8018505502678365e-2,+                               unseen = -4.04305126783455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 55},+                   koData =+                     ClassData{prior = -4.02535169073515, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.276666119016055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 70},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> sharp",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.2992829841302609),+                                    ("time-of-day (latent)", -1.2992829841302609),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = -0.8209805520698302,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.7578579175523736),+                                    ("daymonth", -1.4213856809311607),+                                    ("named-daylast <cycle>", -2.6741486494265287),+                                    ("named-daynext <cycle>", -2.6741486494265287),+                                    ("named-dayintersect", -2.268683541318364),+                                    ("dayweek", -1.575536360758419),+                                    ("named-daythis <cycle>", -1.9810014688665833)],+                               n = 11},+                   koData =+                     ClassData{prior = -0.579818495252942, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.3581234841531944),+                                    ("daymonth", -0.8472978603872037),+                                    ("named-dayintersect", -1.6094379124341003)],+                               n = 14}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.580450375560848), ("day", -1.916922612182061),+                                    ("year", -2.4277482359480516),+                                    ("<integer> <unit-of-duration>", -0.8873031950009028),+                                    ("a <unit-of-duration>", -2.833213344056216),+                                    ("month", -2.4277482359480516)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -2.751535313041949, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.540445040947149), ("named-day", -1.540445040947149),+                                    ("hour", -1.9459101490553135),+                                    ("week-end", -1.9459101490553135)],+                               n = 3},+                   koData =+                     ClassData{prior = -6.59579677917974e-2,+                               unseen = -4.574710978503383,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)", -1.6199092123013958),+                                    ("day", -2.367123614131617),+                                    ("time-of-day (latent)", -1.6199092123013958),+                                    ("year", -1.6199092123013958),+                                    ("named-day", -2.9549102790337356),+                                    ("intersect by \"of\", \"from\", \"'s\"", -2.9549102790337356),+                                    ("hour", -1.6199092123013958)],+                               n = 44}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.25131442828090605,+                               unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -0.8649974374866046),+                                    ("hour", -0.8649974374866046)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.5040773967762742,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.5040773967762742),+                                    ("hh:mm", -1.5040773967762742),+                                    ("minute", -1.0986122886681098)],+                               n = 2}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.6931471805599453),+                                    ("integer (0..19)", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("decimal number",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.9459101490553135),+                                    ("day", -1.0296194171811581),+                                    ("named-day", -1.0296194171811581),+                                    ("month", -1.9459101490553135)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.8109302162163288,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("month (grain)", -2.0794415416798357),+                                    ("year (grain)", -2.0794415416798357),+                                    ("week (grain)", -1.6739764335716716),+                                    ("year", -2.0794415416798357), ("month", -2.0794415416798357)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("week (grain)", -1.6739764335716716),+                                    ("day", -1.6739764335716716),+                                    ("day (grain)", -1.6739764335716716)],+                               n = 4}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.793208009442517),+                                    ("integer (0..19)year (grain)", -3.1986731175506815),+                                    ("integer (numeric)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)hour (grain)", -3.1986731175506815),+                                    ("second", -2.793208009442517),+                                    ("integer (numeric)second (grain)", -3.1986731175506815),+                                    ("integer (numeric)year (grain)", -3.1986731175506815),+                                    ("day", -2.793208009442517), ("year", -2.793208009442517),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("integer (0..19)month (grain)", -3.1986731175506815),+                                    ("integer (0..19)second (grain)", -3.1986731175506815),+                                    ("hour", -2.793208009442517), ("month", -2.793208009442517),+                                    ("integer (numeric)minute (grain)", -3.1986731175506815),+                                    ("integer (0..19)minute (grain)", -3.1986731175506815),+                                    ("integer (numeric)month (grain)", -3.1986731175506815),+                                    ("minute", -2.793208009442517),+                                    ("integer (numeric)hour (grain)", -3.1986731175506815),+                                    ("integer (0..19)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)week (grain)", -3.1986731175506815)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.418840607796598,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.0204248861443626),+                                    ("<integer> more <unit-of-duration>", -3.3081069585961433),+                                    ("number.number hours", -3.713572066704308),+                                    ("second", -2.797281334830153), ("day", -2.6149597780361984),+                                    ("half an hour", -3.713572066704308),+                                    ("<integer> <unit-of-duration>", -1.2286654169163076),+                                    ("a <unit-of-duration>", -2.797281334830153),+                                    ("<integer> and an half hours", -3.3081069585961433),+                                    ("hour", -2.6149597780361984), ("minute", -1.4622802680978126),+                                    ("about <duration>", -3.3081069585961433)],+                               n = 35},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6649763035932491, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.252762968495368),+                                    ("hh:mmhh:mm", -1.252762968495368),+                                    ("dayday", -2.1000608288825715),+                                    ("<day-of-month> (non ordinal) <named-month><day-of-month> (non ordinal) <named-month>",+                                     -2.1000608288825715)],+                               n = 18},+                   koData =+                     ClassData{prior = -0.7221347174331976, unseen = -3.871201010907891,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -2.0583881324820035),+                                    ("minuteminute", -1.9042374526547454),+                                    ("hh:mmhh:mm", -3.1570004211501135),+                                    ("dayyear", -2.751535313041949),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -2.751535313041949),+                                    ("hh:mmintersect", -2.0583881324820035),+                                    ("dd/mmyear", -2.751535313041949),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -2.0583881324820035),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -2.751535313041949),+                                    ("minuteyear", -2.751535313041949),+                                    ("yearminute", -2.751535313041949)],+                               n = 17}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.7672551527136672,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.7621400520468967),+                                    ("hh:mmhh:mm", -0.7621400520468967)],+                               n = 13},+                   koData =+                     ClassData{prior = -0.6241543090729939,+                               unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.8183103235139514),+                                    ("minuteminute", -2.833213344056216),+                                    ("hh:mmhh:mm", -2.833213344056216),+                                    ("minutehour", -0.8183103235139514)],+                               n = 15}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.04305126783455,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.639057329615259),+                                    ("integer (0..19)year (grain)", -3.332204510175204),+                                    ("integer (numeric)day (grain)", -2.9267394020670396),+                                    ("second", -2.9267394020670396),+                                    ("integer (numeric)second (grain)", -3.332204510175204),+                                    ("integer (numeric)year (grain)", -2.9267394020670396),+                                    ("day", -2.639057329615259), ("year", -2.639057329615259),+                                    ("integer (numeric)week (grain)", -3.332204510175204),+                                    ("integer (0..19)month (grain)", -2.9267394020670396),+                                    ("integer (0..19)second (grain)", -3.332204510175204),+                                    ("hour", -2.9267394020670396), ("month", -2.639057329615259),+                                    ("integer (numeric)minute (grain)", -3.332204510175204),+                                    ("integer (0..19)minute (grain)", -3.332204510175204),+                                    ("integer (numeric)month (grain)", -3.332204510175204),+                                    ("minute", -2.9267394020670396),+                                    ("integer (numeric)hour (grain)", -2.9267394020670396),+                                    ("integer (0..19)day (grain)", -3.332204510175204),+                                    ("integer (0..19)week (grain)", -2.9267394020670396)],+                               n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.4418327522790392, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 5}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 18},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3}}),+       ("<hour-of-day> half (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("about <time-of-day>", -1.7346010553881064),+                                    ("time-of-day (latent)", -1.041453874828161),+                                    ("hour", -0.7537718023763802)],+                               n = 7}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.4816045409242156),+                                    ("week (grain)named-month", -1.9924301646902063),+                                    ("day (grain)intersect", -1.9924301646902063),+                                    ("weekmonth", -1.4816045409242156),+                                    ("day (grain)named-month", -1.9924301646902063),+                                    ("week (grain)intersect", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.0986122886681098),+                                    ("ordinal (digits)named-month", -1.5040773967762742),+                                    ("month", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.7537718023763802, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.6863989535702288),+                                    ("intersect", -2.1972245773362196),+                                    ("tomorrow", -2.1972245773362196), ("day", -2.1972245773362196),+                                    ("hour", -1.349926716949016)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.6359887667199967,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("this <part-of-day>", -2.268683541318364),+                                    ("christmas eve", -2.268683541318364),+                                    ("in|during the <part-of-day>", -2.268683541318364),+                                    ("day", -2.268683541318364), ("hh:mm", -2.6741486494265287),+                                    ("hour", -1.4213856809311607), ("minute", -2.6741486494265287),+                                    ("this <time>", -2.268683541318364)],+                               n = 9}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = -4.8790164169432056e-2,+                               unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -3.044522437723423, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 10}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -1.3217558399823195, unseen = -3.828641396489095,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.1972245773362196), ("intersect", -2.70805020110221),+                                    ("season", -2.1972245773362196),+                                    ("next <cycle>", -3.1135153092103742),+                                    ("named-month", -2.70805020110221),+                                    ("day", -2.1972245773362196),+                                    ("this <cycle>", -2.4203681286504293),+                                    ("hour", -2.1972245773362196), ("evening", -3.1135153092103742),+                                    ("month", -2.1972245773362196),+                                    ("morning", -3.1135153092103742),+                                    ("week-end", -2.70805020110221)],+                               n = 16},+                   koData =+                     ClassData{prior = -0.3101549283038396, unseen = -4.624972813284271,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.0501711593797225),+                                    ("named-month", -1.670681537674819),+                                    ("time-of-day (latent)", -3.5165082281731497),+                                    ("hour", -1.9070703157390494), ("month", -1.1811333123561132),+                                    ("morning", -2.0501711593797225)],+                               n = 44}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/DE.hs view
@@ -0,0 +1,1824 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.DE (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -1.3862943611198906),+                                    ("hh:mm", -1.3862943611198906), ("hour", -1.3862943611198906),+                                    ("minute", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.668083211896729, unseen = -4.634728988229636,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 101},+                   koData =+                     ClassData{prior = -0.7188555372701523, unseen = -4.584967478670572,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 96}}),+       ("exactly <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.0986122886681098),+                                    ("<time-of-day>  o'clock", -1.5040773967762742),+                                    ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Father's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <half> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -5.720311776607412,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clockmorning", -4.618415412738112),+                                    ("until <time-of-day>afternoon", -5.0238805208462765),+                                    ("dayhour", -3.319132428607851),+                                    ("todayevening", -4.618415412738112),+                                    ("half <integer> (german style hour-of-day)afternoon",+                                     -5.0238805208462765),+                                    ("<time-of-day>  o'clockafter lunch", -4.330733340286331),+                                    ("intersect by ','evening", -3.5198031240700023),+                                    ("<time-of-day>  o'clockon <date>", -3.925268232178167),+                                    ("intersectevening", -1.9558275857126592),+                                    ("time-of-day (latent)on <date>", -4.330733340286331),+                                    ("about <time-of-day>on <date>", -4.618415412738112),+                                    ("<hour-of-day> <integer> (as relative minutes)in|during the <part-of-day>",+                                     -4.618415412738112),+                                    ("hourhour", -1.1952391243571814),+                                    ("<time-of-day>  o'clockin|during the <part-of-day>",+                                     -3.925268232178167),+                                    ("<time-of-day>  o'clockafternoon", -4.330733340286331),+                                    ("half <integer> (german style hour-of-day)after lunch",+                                     -5.0238805208462765),+                                    ("until <time-of-day>morning", -4.618415412738112),+                                    ("minutehour", -2.384823191231018),+                                    ("at <time-of-day>in|during the <part-of-day>",+                                     -4.107589788972121),+                                    ("<hour-of-day> <integer> (as relative minutes)after lunch",+                                     -5.0238805208462765),+                                    ("<time-of-day> am|pmmorning", -4.618415412738112),+                                    ("tomorrowevening", -5.0238805208462765),+                                    ("time-of-day (latent)morning", -5.0238805208462765),+                                    ("named-daymorning", -4.618415412738112),+                                    ("hh:mmmorning", -5.0238805208462765),+                                    ("half <integer> (german style hour-of-day)in|during the <part-of-day>",+                                     -4.618415412738112),+                                    ("until <time-of-day>on <date>", -5.0238805208462765),+                                    ("<day-of-month>(ordinal) <named-month>morning",+                                     -5.0238805208462765),+                                    ("<time-of-day>  o'clockevening", -5.0238805208462765),+                                    ("hh:mmon <date>", -4.107589788972121),+                                    ("<hour-of-day> <integer> (as relative minutes)afternoon",+                                     -5.0238805208462765),+                                    ("tomorrowlunch", -4.618415412738112),+                                    ("until <time-of-day>after lunch", -5.0238805208462765),+                                    ("at <time-of-day>on <date>", -4.107589788972121),+                                    ("yesterdayevening", -5.0238805208462765),+                                    ("intersectmorning", -5.0238805208462765),+                                    ("hh:mmin|during the <part-of-day>", -4.107589788972121),+                                    ("time-of-day (latent)in|during the <part-of-day>",+                                     -4.330733340286331),+                                    ("<hour-of-day> <integer> (as relative minutes)on <date>",+                                     -4.618415412738112),+                                    ("about <time-of-day>in|during the <part-of-day>",+                                     -4.618415412738112),+                                    ("half <integer> (german style hour-of-day)on <date>",+                                     -4.618415412738112),+                                    ("at <time-of-day>morning", -5.0238805208462765),+                                    ("until <time-of-day>in|during the <part-of-day>",+                                     -5.0238805208462765)],+                               n = 128},+                   koData =+                     ClassData{prior = -2.1972245773362196, unseen = -4.394449154672439,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -3.283414346005772),+                                    ("year (latent)on <date>", -3.6888794541139363),+                                    ("<time-of-day>  o'clockafter lunch", -3.6888794541139363),+                                    ("intersectevening", -2.995732273553991),+                                    ("monthhour", -3.6888794541139363),+                                    ("time-of-day (latent)on <date>", -2.772588722239781),+                                    ("hourhour", -1.742969305058623),+                                    ("<time-of-day>  o'clockafternoon", -3.6888794541139363),+                                    ("year (latent)in|during the <part-of-day>",+                                     -3.6888794541139363),+                                    ("named-monthmorning", -3.6888794541139363),+                                    ("time-of-day (latent)in|during the <part-of-day>",+                                     -2.772588722239781)],+                               n = 16}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.20972053098206903,+                               unseen = -4.276666119016055,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -2.065455299705096),+                                    ("half <integer> (german style hour-of-day)",+                                     -3.56953269648137),+                                    ("about <time-of-day>", -3.164067588373206),+                                    ("time-of-day (latent)", -1.6236225474260568),+                                    ("relative minutes after|past <integer> (hour-of-day)",+                                     -3.56953269648137),+                                    ("hh:mm", -2.8763855159214247),+                                    ("quarter after|past <integer> (hour-of-day)",+                                     -3.56953269648137),+                                    ("hour", -1.08462604669337), ("minute", -2.1832383353614793),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.56953269648137)],+                               n = 30},+                   koData =+                     ClassData{prior = -1.6650077635889111, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.6094379124341003),+                                    ("<time-of-day> am|pm", -1.8325814637483102),+                                    ("hour", -1.4271163556401458), ("minute", -2.120263536200091)],+                               n = 7}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -2.03688192726104), ("day", -0.7375989431307791),+                                    ("named-day", -0.9382696385929302)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = -0.20409535634351528,+                               unseen = -4.820281565605037,+                               likelihoods =+                                 HashMap.fromList+                                   [("mm/dd", -4.119037174812472),+                                    ("absorption of , after named day", -3.713572066704308),+                                    ("intersect", -1.867745376205977),+                                    ("after lunch", -2.866274206317104),+                                    ("day", -1.4799798451972137), ("afternoon", -2.866274206317104),+                                    ("named-day", -2.866274206317104),+                                    ("intersect by ','", -2.866274206317104),+                                    ("intersect by 'of', 'from', 's", -3.4258899942525267),+                                    ("<day-of-month> (ordinal)", -3.713572066704308),+                                    ("hour", -1.9218125974762528), ("evening", -4.119037174812472),+                                    ("<datetime> - <datetime> (interval)", -4.119037174812472),+                                    ("minute", -2.509599262378372),+                                    ("morning", -4.119037174812472)],+                               n = 53},+                   koData =+                     ClassData{prior = -1.6894806201076367,+                               unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.6341305250244718),+                                    ("after lunch", -3.0204248861443626),+                                    ("<day-of-month>(ordinal) <named-month>", -3.0204248861443626),+                                    ("tomorrow", -3.0204248861443626), ("day", -2.1041341542702074),+                                    ("intersect by 'of', 'from', 's", -3.0204248861443626),+                                    ("<day-of-month> (ordinal)", -3.0204248861443626),+                                    ("hour", -3.0204248861443626), ("minute", -1.6341305250244718)],+                               n = 12}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36},+                   koData =+                     ClassData{prior = -2.3025850929940455, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("hh:mmhh:mm", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.0986122886681098),+                                    ("minutehour", -1.0986122886681098)],+                               n = 1}}),+       ("between <datetime> and <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("hh:mmhh:mm", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.0986122886681098),+                                    ("minutehour", -1.0986122886681098)],+                               n = 1}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day>  o'clock",+        Classifier{okData =+                     ClassData{prior = -4.348511193973878e-2,+                               unseen = -4.61512051684126,+                               likelihoods =+                                 HashMap.fromList+                                   [("exactly <time-of-day>", -3.912023005428146),+                                    ("at <time-of-day>", -2.4079456086518722),+                                    ("half <integer> (german style hour-of-day)",+                                     -3.912023005428146),+                                    ("about <time-of-day>", -3.2188758248682006),+                                    ("time-of-day (latent)", -1.3470736479666092),+                                    ("quarter after|past <integer> (hour-of-day)",+                                     -3.912023005428146),+                                    ("until <time-of-day>", -3.2188758248682006),+                                    ("hour", -0.8209805520698302), ("minute", -3.506557897319982),+                                    ("after <time-of-day>", -3.2188758248682006)],+                               n = 45},+                   koData =+                     ClassData{prior = -3.1570004211501135, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.9459101490553135),+                                    ("hour", -1.540445040947149),+                                    ("after <time-of-day>", -1.9459101490553135)],+                               n = 2}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..19th)quarter (grain)", -0.916290731874155),+                                    ("quarter", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -0.916290731874155),+                                    ("quarter", -0.916290731874155)],+                               n = 1}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.24751603072644626, unseen = -6.8001700683022,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect by ','named-month", -4.49647076906475),+                                    ("hourday", -4.8531457130034825),+                                    ("dayhour", -2.481567748522486),+                                    ("daymonth", -3.3333199592590694),+                                    ("<day-of-month>(ordinal) <named-month> year<time-of-day>  o'clock",+                                     -6.105908681498851),+                                    ("monthyear", -4.49647076906475),+                                    ("yearhour", -6.105908681498851),+                                    ("intersect<time-of-day>  o'clock", -3.9658425180025803),+                                    ("christmasyear", -6.105908681498851),+                                    ("after lunchat <time-of-day>", -6.105908681498851),+                                    ("named-daylast <cycle>", -6.105908681498851),+                                    ("intersect by 'of', 'from', 'syear", -5.700443573390687),+                                    ("<time-of-day> am|pmintersect", -5.0072963928307415),+                                    ("intersect<time> <part-of-day>", -4.026467139819015),+                                    ("<time-of-day>  o'clockafter lunch", -5.412761500938905),+                                    ("<time> <part-of-day><time-of-day>  o'clock",+                                     -6.105908681498851),+                                    ("today<time-of-day>  o'clock", -6.105908681498851),+                                    ("<time-of-day>  o'clockon <date>", -5.700443573390687),+                                    ("<time-of-day> am|pmintersect by ','", -5.412761500938905),+                                    ("intersect by ','year", -5.700443573390687),+                                    ("on <date><time-of-day>  o'clock", -6.105908681498851),+                                    ("exactly <time-of-day>tomorrow", -5.700443573390687),+                                    ("monthhour", -5.700443573390687),+                                    ("on <date>between <datetime> and <datetime> (interval)",+                                     -6.105908681498851),+                                    ("last <day-of-week> of <time>year", -6.105908681498851),+                                    ("hourmonth", -5.700443573390687),+                                    ("todayat <time-of-day>", -5.412761500938905),+                                    ("on <date>between <time-of-day> and <time-of-day> (interval)",+                                     -6.105908681498851),+                                    ("on <date>at <time-of-day>", -5.700443573390687),+                                    ("named-dayhh:mm", -6.105908681498851),+                                    ("dayday", -3.1881379494145716),+                                    ("<time> <part-of-day>at <time-of-day>", -5.700443573390687),+                                    ("<time-of-day> am|pmabsorption of , after named day",+                                     -6.105908681498851),+                                    ("about <time-of-day>on <date>", -6.105908681498851),+                                    ("<hour-of-day> <integer> (as relative minutes)in|during the <part-of-day>",+                                     -5.700443573390687),+                                    ("<day-of-month> (ordinal)intersect", -5.1896179496246955),+                                    ("hourhour", -3.5801800371905954),+                                    ("<part-of-day> of <time>named-month", -5.700443573390687),+                                    ("hh:mmintersect by ','", -4.8531457130034825),+                                    ("intersectnamed-month", -3.3333199592590694),+                                    ("dayyear", -3.9086841041626315),+                                    ("<time-of-day>  o'clockin|during the <part-of-day>",+                                     -5.0072963928307415),+                                    ("tomorrow<time-of-day>  o'clock", -6.105908681498851),+                                    ("<time-of-day>  o'clocktomorrow", -5.412761500938905),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -6.105908681498851),+                                    ("half <integer> (german style hour-of-day)after lunch",+                                     -6.105908681498851),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month>",+                                     -5.0072963928307415),+                                    ("hourminute", -5.412761500938905),+                                    ("on <date><day-of-month>(ordinal) <named-month>",+                                     -5.700443573390687),+                                    ("minutemonth", -3.431760032072322),+                                    ("minutehour", -3.8546168828923557),+                                    ("named-day<time> timezone", -6.105908681498851),+                                    ("at <time-of-day>in|during the <part-of-day>",+                                     -5.1896179496246955),+                                    ("named-monthyear", -4.49647076906475),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month> year",+                                     -6.105908681498851),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -5.0072963928307415),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -6.105908681498851),+                                    ("<day-of-month>(ordinal) <named-month> year<time> <part-of-day>",+                                     -6.105908681498851),+                                    ("<hour-of-day> <integer> (as relative minutes)after lunch",+                                     -6.105908681498851),+                                    ("named-day<datetime> - <datetime> (interval)",+                                     -6.105908681498851),+                                    ("on <date>named-month", -5.1896179496246955),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -4.71961432037896),+                                    ("this <part-of-day><time-of-day>  o'clock",+                                     -6.105908681498851),+                                    ("<day-of-month>(ordinal) <named-month>intersect",+                                     -6.105908681498851),+                                    ("hh:mmintersect", -3.6635616461296463),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -5.700443573390687),+                                    ("named-daynext <cycle>", -6.105908681498851),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -5.412761500938905),+                                    ("<day-of-month> (ordinal)named-day", -5.700443573390687),+                                    ("intersect by ','intersect", -5.0072963928307415),+                                    ("half <integer> (german style hour-of-day)in|during the <part-of-day>",+                                     -5.700443573390687),+                                    ("at <time-of-day>intersect", -4.314149212270796),+                                    ("on <date>from <time-of-day> - <time-of-day> (interval)",+                                     -5.700443573390687),+                                    ("<time> <part-of-day>from <time-of-day> - <time-of-day> (interval)",+                                     -6.105908681498851),+                                    ("absorption of , after named day<day-of-month> (ordinal)",+                                     -5.0072963928307415),+                                    ("dayminute", -3.9086841041626315),+                                    ("on <date>from <datetime> - <datetime> (interval)",+                                     -6.105908681498851),+                                    ("<time> <part-of-day>from <datetime> - <datetime> (interval)",+                                     -6.105908681498851),+                                    ("intersectyear", -4.8531457130034825),+                                    ("on <date>intersect", -5.700443573390687),+                                    ("on <date><day-of-month> (ordinal)", -5.700443573390687),+                                    ("<ordinal> <cycle> of <time>year", -6.105908681498851),+                                    ("minuteday", -2.1262270275968898),+                                    ("absorption of , after named dayintersect",+                                     -3.9658425180025803),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -6.105908681498851),+                                    ("<datetime> - <datetime> (interval)named-month",+                                     -5.700443573390687),+                                    ("year<time-of-day>  o'clock", -6.105908681498851),+                                    ("at <time-of-day>intersect by ','", -5.412761500938905),+                                    ("named-dayat <time-of-day>", -5.700443573390687),+                                    ("hh:mmabsorption of , after named day", -5.700443573390687),+                                    ("<time-of-day> am|pmnamed-day", -6.105908681498851),+                                    ("intersect by ','<time> <part-of-day>", -5.1896179496246955),+                                    ("hh:mmon <date>", -3.6635616461296463),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -6.105908681498851),+                                    ("at <time-of-day>absorption of , after named day",+                                     -6.105908681498851),+                                    ("until <time-of-day>after lunch", -6.105908681498851),+                                    ("mm/ddyear", -6.105908681498851),+                                    ("intersect by ','<time-of-day>  o'clock", -5.1896179496246955),+                                    ("intersect<day-of-month> (ordinal)", -4.71961432037896),+                                    ("named-day<time-of-day>  o'clock", -6.105908681498851),+                                    ("<day-of-month> (ordinal)intersect by 'of', 'from', 's",+                                     -5.412761500938905),+                                    ("at <time-of-day>on <date>", -4.23410650459726),+                                    ("intersectintersect", -4.026467139819015),+                                    ("dayweek", -5.0072963928307415),+                                    ("weekyear", -5.700443573390687),+                                    ("hh:mmin|during the <part-of-day>", -5.1896179496246955),+                                    ("named-monthintersect", -6.105908681498851),+                                    ("<day-of-month> (ordinal)named-month", -4.401160589260425),+                                    ("tomorrowat <time-of-day>", -5.700443573390687),+                                    ("<hour-of-day> <integer> (as relative minutes)on <date>",+                                     -6.105908681498851),+                                    ("named-daythis <cycle>", -5.412761500938905),+                                    ("at <time-of-day>tomorrow", -6.105908681498851),+                                    ("about <time-of-day>in|during the <part-of-day>",+                                     -5.700443573390687),+                                    ("half <integer> (german style hour-of-day)on <date>",+                                     -6.105908681498851),+                                    ("this <part-of-day>at <time-of-day>", -5.700443573390687),+                                    ("after lunch<hour-of-day> <integer> (as relative minutes)",+                                     -5.700443573390687),+                                    ("last <cycle> of <time>year", -5.700443573390687),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -6.105908681498851),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -6.105908681498851)],+                               n = 381},+                   koData =+                     ClassData{prior = -1.517486571391241, unseen = -5.857933154483459,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect by ','named-month", -4.468777561082536),+                                    ("named-day<part-of-day> of <time>", -5.161924741642482),+                                    ("dayhour", -4.468777561082536),+                                    ("daymonth", -3.2901225647408903),+                                    ("monthday", -4.756459633534318),+                                    ("monthyear", -5.161924741642482),+                                    ("yearhour", -5.161924741642482),+                                    ("after lunchat <time-of-day>", -4.756459633534318),+                                    ("intersect by 'of', 'from', 'syear", -4.468777561082536),+                                    ("<time-of-day> am|pmintersect", -3.457176649404057),+                                    ("intersect<time> <part-of-day>", -5.161924741642482),+                                    ("<time-of-day>  o'clockafter lunch", -5.161924741642482),+                                    ("<day-of-month> (ordinal)year", -5.161924741642482),+                                    ("after lunch<time-of-day>  o'clock", -5.161924741642482),+                                    ("at <time-of-day>named-day", -5.161924741642482),+                                    ("<time-of-day> am|pmintersect by ','", -3.909161773147114),+                                    ("<time-of-day>  o'clock<time> <part-of-day>",+                                     -4.2456340097683265),+                                    ("monthhour", -5.161924741642482),+                                    ("on <date>between <datetime> and <datetime> (interval)",+                                     -5.161924741642482),+                                    ("todayat <time-of-day>", -5.161924741642482),+                                    ("on <date>between <time-of-day> and <time-of-day> (interval)",+                                     -5.161924741642482),+                                    ("named-dayhh:mm", -5.161924741642482),+                                    ("dayday", -3.909161773147114),+                                    ("<time-of-day> am|pmabsorption of , after named day",+                                     -4.756459633534318),+                                    ("hourhour", -3.657847344866208),+                                    ("intersectnamed-month", -3.5524868292083815),+                                    ("dayyear", -4.0633124529743725),+                                    ("minutemonth", -3.2160145925871686),+                                    ("named-monthyear", -5.161924741642482),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -5.161924741642482),+                                    ("on <date>named-month", -5.161924741642482),+                                    ("absorption of , after named daynamed-month",+                                     -4.0633124529743725),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -4.468777561082536),+                                    ("named-dayafter <time-of-day>", -4.756459633534318),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.756459633534318),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -5.161924741642482),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.468777561082536),+                                    ("<day-of-month> (ordinal)named-day", -4.468777561082536),+                                    ("at <time-of-day>intersect", -4.0633124529743725),+                                    ("on <date>from <time-of-day> - <time-of-day> (interval)",+                                     -4.756459633534318),+                                    ("dayminute", -3.0218585781462113),+                                    ("on <date>from <datetime> - <datetime> (interval)",+                                     -5.161924741642482),+                                    ("minuteday", -2.1661924680884908),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -5.161924741642482),+                                    ("at <time-of-day>intersect by ','", -4.468777561082536),+                                    ("<time-of-day> am|pmnamed-day", -4.756459633534318),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -5.161924741642482),+                                    ("at <time-of-day>absorption of , after named day",+                                     -5.161924741642482),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -4.756459633534318),+                                    ("year<time> <part-of-day>", -5.161924741642482),+                                    ("intersect<day-of-month> (ordinal)", -4.468777561082536),+                                    ("<day-of-month> (ordinal)intersect by 'of', 'from', 's",+                                     -4.756459633534318),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -4.756459633534318),+                                    ("intersectintersect", -4.468777561082536),+                                    ("<day-of-month> (ordinal)named-month", -4.468777561082536),+                                    ("until <time-of-day>named-month", -5.161924741642482),+                                    ("after <time-of-day>year", -5.161924741642482),+                                    ("on <date>after <time-of-day>", -5.161924741642482),+                                    ("tomorrownoon", -5.161924741642482)],+                               n = 107}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7047480922384253),+                                    ("ordinals (first..19th)week (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (first..19th)day (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (first..19th)week (grain)intersect",+                                     -1.7047480922384253),+                                    ("weekmonth", -1.2992829841302609)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.3862943611198906),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -1.791759469228055),+                                    ("hh:mmhh:mm", -1.3862943611198906),+                                    ("hourhour", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.2039728043259361),+                                    ("minutehour", -1.2039728043259361)],+                               n = 2}}),+       ("after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("month (grain)", -2.3025850929940455),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.6094379124341003),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("month", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("week (grain)", -1.6094379124341003)],+                               n = 1}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.252762968495368),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -1.9459101490553135),+                                    ("hh:mmhh:mm", -1.252762968495368),+                                    ("hourhour", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.0986122886681098),+                                    ("minutehour", -1.0986122886681098)],+                               n = 3}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("couple",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinal (digits)quarter (grain)year", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Allerheiligen",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7884573603642702),+                                    ("ordinals (first..19th)named-dayintersect",+                                     -1.0116009116784799),+                                    ("ordinals (first..19th)named-daynamed-month",+                                     -1.7047480922384253)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.8109302162163288),+                                    ("ordinals (first..19th)named-daynamed-month",+                                     -0.8109302162163288)],+                               n = 3}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.8501476017100584,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 45},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<part-of-day> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -0.9444616088408514),+                                    ("morning<day-of-month>(ordinal) <named-month>",+                                     -1.791759469228055),+                                    ("morningintersect", -1.791759469228055),+                                    ("morning<day-of-month> (ordinal)", -1.791759469228055)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourhour", -1.3862943611198906),+                                    ("morningtime-of-day (latent)", -1.3862943611198906)],+                               n = 1}}),+       ("valentine's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half <integer> (german style hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -1.7047480922384253),+                                    ("time-of-day (latent)", -1.0116009116784799),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("evening", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.262364264467491, unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.832909122935104),+                                    ("month", -0.7375989431307791),+                                    ("ordinals (first..19th)named-month", -2.4423470353692043)],+                               n = 10},+                   koData =+                     ClassData{prior = -1.466337068793427, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.8109302162163288),+                                    ("month", -0.8109302162163288)],+                               n = 3}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 7}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -6.0624621816434854e-2,+                               unseen = -3.6375861597263857,+                               likelihoods =+                                 HashMap.fromList+                                   [("after lunch", -1.6650077635889111),+                                    ("afternoon", -1.5314763709643884),+                                    ("hour", -0.7777045685880083), ("evening", -2.512305623976115),+                                    ("morning", -2.917770732084279)],+                               n = 16},+                   koData =+                     ClassData{prior = -2.833213344056216, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("after lunch", -1.252762968495368),+                                    ("hour", -1.252762968495368)],+                               n = 1}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after next <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.3862943611198906),+                                    ("day", -1.3862943611198906),+                                    ("named-day", -1.3862943611198906),+                                    ("month", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2039728043259361),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.2039728043259361),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -1.3862943611198906),+                                    ("time-of-day (latent)", -1.3862943611198906),+                                    ("hour", -0.8266785731844679)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.3862943611198906),+                                    ("<time-of-day> am|pm", -1.3862943611198906),+                                    ("hour", -0.9808292530117262)],+                               n = 2}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.8082165103447325,+                               unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.1466034741918754),+                                    ("integer (0..19)", -2.174751721484161)],+                               n = 41},+                   koData =+                     ClassData{prior = -0.5899629443247145, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.587786664902119),+                                    ("integer (0..19)", -0.9444616088408514),+                                    ("couple", -2.890371757896165)],+                               n = 51}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.8109302162163288),+                                    ("named-dayintersect", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.8850381883700507, unseen = -4.330733340286331,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.2380465718564744),+                                    ("integer (0..19)year (grain)", -3.2188758248682006),+                                    ("integer (numeric)day (grain)", -2.70805020110221),+                                    ("couplehour (grain)", -3.624340932976365),+                                    ("integer (0..19)hour (grain)", -3.2188758248682006),+                                    ("second", -3.624340932976365),+                                    ("integer (numeric)year (grain)", -3.624340932976365),+                                    ("day", -2.70805020110221), ("year", -2.9311937524164198),+                                    ("integer (numeric)week (grain)", -2.9311937524164198),+                                    ("integer (0..19)month (grain)", -3.624340932976365),+                                    ("integer (0..19)second (grain)", -3.624340932976365),+                                    ("hour", -2.70805020110221), ("month", -3.624340932976365),+                                    ("integer (numeric)minute (grain)", -2.5257286443082556),+                                    ("integer (0..19)minute (grain)", -3.624340932976365),+                                    ("minute", -2.371577964480997),+                                    ("integer (numeric)hour (grain)", -3.624340932976365),+                                    ("integer (0..19)week (grain)", -2.70805020110221)],+                               n = 26},+                   koData =+                     ClassData{prior = -0.5322168137473082, unseen = -4.584967478670572,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.62880082944807),+                                    ("integer (0..19)year (grain)", -2.9652730660692823),+                                    ("integer (numeric)day (grain)", -3.4760986898352733),+                                    ("integer (0..19)hour (grain)", -3.8815637979434374),+                                    ("second", -2.9652730660692823),+                                    ("integer (numeric)second (grain)", -3.4760986898352733),+                                    ("integer (numeric)year (grain)", -3.4760986898352733),+                                    ("day", -2.3774864011671633), ("year", -2.62880082944807),+                                    ("integer (numeric)week (grain)", -3.188416617383492),+                                    ("integer (0..19)month (grain)", -2.9652730660692823),+                                    ("integer (0..19)second (grain)", -3.4760986898352733),+                                    ("hour", -3.188416617383492), ("month", -2.62880082944807),+                                    ("integer (numeric)minute (grain)", -3.4760986898352733),+                                    ("integer (0..19)minute (grain)", -3.4760986898352733),+                                    ("integer (numeric)month (grain)", -3.4760986898352733),+                                    ("minute", -2.9652730660692823),+                                    ("coupleday (grain)", -3.4760986898352733),+                                    ("integer (numeric)hour (grain)", -3.4760986898352733),+                                    ("integer (0..19)day (grain)", -2.9652730660692823),+                                    ("integer (0..19)week (grain)", -3.188416617383492)],+                               n = 37}}),+       ("ordinals (first..19th)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -1.845826690498331, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -2.0794415416798357),+                                    ("hh:mm", -2.0794415416798357),+                                    ("until <time-of-day>", -2.0794415416798357),+                                    ("hour", -1.6739764335716716), ("minute", -2.0794415416798357)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.17185025692665928,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -2.3513752571634776),+                                    ("<time-of-day>  o'clock", -2.3513752571634776),+                                    ("half <integer> (german style hour-of-day)",+                                     -3.044522437723423),+                                    ("about <time-of-day>", -3.044522437723423),+                                    ("time-of-day (latent)", -2.128231705849268),+                                    ("hh:mm", -2.3513752571634776), ("hour", -1.4350845252893227),+                                    ("minute", -1.6582280766035324),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.044522437723423)],+                               n = 16}}),+       ("<duration> after <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("a <unit-of-duration>christmas", -1.252762968495368),+                                    ("<integer> <unit-of-duration>christmas", -1.252762968495368),+                                    ("yearday", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8472978603872037),+                                    ("integer (numeric)time-of-day (latent)", -1.252762968495368),+                                    ("integer (20..90)time-of-day (latent)", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9924301646902063),+                                    ("hour (grain)", -2.3978952727983707),+                                    ("year (grain)", -2.3978952727983707),+                                    ("second", -2.3978952727983707),+                                    ("week (grain)", -1.9924301646902063),+                                    ("minute (grain)", -2.3978952727983707),+                                    ("year", -2.3978952727983707),+                                    ("second (grain)", -2.3978952727983707),+                                    ("hour", -2.3978952727983707), ("minute", -2.3978952727983707)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -3.17486983145803e-2,+                               unseen = -3.4965075614664802,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 31},+                   koData =+                     ClassData{prior = -3.4657359027997265,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -1.5040773967762742),+                                    ("time-of-day (latent)", -1.0986122886681098),+                                    ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.02535169073515,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 54},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> before <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>time-of-day (latent)",+                                     -0.6931471805599453),+                                    ("minutehour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by ','",+        Classifier{okData =+                     ClassData{prior = -0.27087495413539975,+                               unseen = -4.6913478822291435,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -2.4849066497880004),+                                    ("named-day<day-of-month> (ordinal)", -3.295836866004329),+                                    ("dayday", -1.463255402256019),+                                    ("dayyear", -3.9889840465642745),+                                    ("on <date><day-of-month>(ordinal) <named-month>",+                                     -3.58351893845611),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.890371757896165),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -3.0726933146901194),+                                    ("named-day<day-of-month>(ordinal) <named-month> year",+                                     -3.9889840465642745),+                                    ("named-dayintersect", -1.9740810260220096),+                                    ("on <date>intersect", -3.58351893845611),+                                    ("on <date><day-of-month> (ordinal)", -3.58351893845611),+                                    ("minuteday", -2.117181869662683),+                                    ("intersect<day-of-month> (ordinal)", -3.0726933146901194),+                                    ("intersectintersect", -3.0726933146901194),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -3.295836866004329),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.9889840465642745)],+                               n = 45},+                   koData =+                     ClassData{prior = -1.4384801142904609,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.03688192726104),+                                    ("daymonth", -2.03688192726104),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -2.4423470353692043),+                                    ("minuteday", -1.5260563034950494),+                                    ("intersect<day-of-month> (ordinal)", -2.4423470353692043),+                                    ("intersectintersect", -2.4423470353692043)],+                               n = 14}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by 'of', 'from', 's",+        Classifier{okData =+                     ClassData{prior = -0.534082485930258, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.793208009442517),+                                    ("daymonth", -1.9459101490553135),+                                    ("named-daylast <cycle>", -3.1986731175506815),+                                    ("on <date>hh:mm", -3.1986731175506815),+                                    ("named-dayhh:mm", -2.793208009442517),+                                    ("intersectnamed-month", -2.793208009442517),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -2.793208009442517),+                                    ("named-day<datetime> - <datetime> (interval)",+                                     -2.793208009442517),+                                    ("on <date><time-of-day> - <time-of-day> (interval)",+                                     -3.1986731175506815),+                                    ("on <date><datetime> - <datetime> (interval)",+                                     -3.1986731175506815),+                                    ("named-daynext <cycle>", -3.1986731175506815),+                                    ("named-dayintersect", -3.1986731175506815),+                                    ("dayminute", -1.589235205116581),+                                    ("intersectintersect", -3.1986731175506815),+                                    ("dayweek", -2.793208009442517)],+                               n = 17},+                   koData =+                     ClassData{prior = -0.8823891801984737,+                               unseen = -3.6888794541139363,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.0541237336955462),+                                    ("daymonth", -1.3609765531356008),+                                    ("intersectnamed-month", -2.5649493574615367),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -2.5649493574615367),+                                    ("on <date><time-of-day> - <time-of-day> (interval)",+                                     -2.9704144655697013),+                                    ("named-dayintersect", -2.277267285009756),+                                    ("dayminute", -2.277267285009756)],+                               n = 12}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.4816045409242156), ("day", -1.9924301646902063),+                                    ("year", -2.3978952727983707),+                                    ("<integer> <unit-of-duration>", -1.0116009116784799),+                                    ("a <unit-of-duration>", -2.3978952727983707),+                                    ("month", -2.3978952727983707)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.9808292530117262),+                                    ("named-day", -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.7672551527136672),+                                    ("hour", -0.7672551527136672)],+                               n = 12}}),+       ("EOM|End of month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.6390799592896695,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..19th)", -1.6582280766035324),+                                    ("ordinal (digits)", -0.2113090936672069)],+                               n = 19},+                   koData =+                     ClassData{prior = -0.750305594399894, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..19th)", -0.9985288301111273),+                                    ("ordinal (digits)", -0.4595323293784402)],+                               n = 17}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3022808718729337, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -1.9459101490553135),+                                    ("<time-of-day>  o'clock", -2.505525936990736),+                                    ("intersect", -3.1986731175506815),+                                    ("time-of-day (latent)", -2.2823823856765264),+                                    ("<time-of-day> am|pm", -3.1986731175506815),+                                    ("EOM|End of month", -3.1986731175506815),+                                    ("hour", -1.0586069540544105), ("month", -3.1986731175506815),+                                    ("midnight|EOD|end of day", -3.1986731175506815)],+                               n = 17},+                   koData =+                     ClassData{prior = -1.3437347467010947, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.6026896854443837),+                                    ("<day-of-month>(ordinal) <named-month>", -2.6026896854443837),+                                    ("day", -1.6863989535702288), ("hh:mm", -2.1972245773362196),+                                    ("<day-of-month> (ordinal)", -2.6026896854443837),+                                    ("<day-of-month> (non ordinal) <named-month>",+                                     -2.6026896854443837),+                                    ("minute", -2.1972245773362196)],+                               n = 6}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (0..19)", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Nikolaus",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("midnight|EOD|end of day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -1.466337068793427, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -2.1972245773362196),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.262364264467491, unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.7841189587656721),+                                    ("hour", -0.7841189587656721)],+                               n = 20}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5040773967762742),+                                    ("month (grain)", -2.1972245773362196),+                                    ("year (grain)", -2.1972245773362196),+                                    ("week (grain)", -1.5040773967762742),+                                    ("year", -2.1972245773362196), ("month", -2.1972245773362196)],+                               n = 5},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("week (grain)", -1.791759469228055),+                                    ("day", -1.791759469228055),+                                    ("day (grain)", -1.791759469228055)],+                               n = 2}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Tag der Deutschen Einheit",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.143134726391533,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.740840023925201),+                                    ("integer (0..19)year (grain)", -3.028522096376982),+                                    ("integer (numeric)day (grain)", -3.4339872044851463),+                                    ("integer (0..19)hour (grain)", -3.4339872044851463),+                                    ("second", -3.028522096376982),+                                    ("integer (numeric)second (grain)", -3.4339872044851463),+                                    ("integer (numeric)year (grain)", -3.4339872044851463),+                                    ("day", -2.3353749158170367), ("year", -2.740840023925201),+                                    ("integer (numeric)week (grain)", -3.4339872044851463),+                                    ("integer (0..19)month (grain)", -3.028522096376982),+                                    ("integer (0..19)second (grain)", -3.4339872044851463),+                                    ("hour", -3.028522096376982), ("month", -2.740840023925201),+                                    ("integer (numeric)minute (grain)", -3.4339872044851463),+                                    ("integer (0..19)minute (grain)", -3.4339872044851463),+                                    ("integer (numeric)month (grain)", -3.4339872044851463),+                                    ("minute", -3.028522096376982),+                                    ("coupleday (grain)", -3.028522096376982),+                                    ("integer (numeric)hour (grain)", -3.4339872044851463),+                                    ("integer (0..19)day (grain)", -3.028522096376982),+                                    ("integer (0..19)week (grain)", -3.028522096376982)],+                               n = 20},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("halloween day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by the end of <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.0986122886681098),+                                    ("hh:mm", -1.791759469228055), ("hour", -1.0986122886681098),+                                    ("minute", -1.791759469228055)],+                               n = 4}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.07753744390572,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6741486494265287),+                                    ("number.number hours", -3.367295829986474),+                                    ("second", -2.9618307218783095), ("day", -2.9618307218783095),+                                    ("half an hour", -3.367295829986474),+                                    ("year", -3.367295829986474),+                                    ("<integer> <unit-of-duration>", -1.2878542883066382),+                                    ("a <unit-of-duration>", -2.451005098112319),+                                    ("<integer> and an half hours", -3.367295829986474),+                                    ("hour", -2.268683541318364), ("minute", -1.6625477377480489),+                                    ("about <duration>", -3.367295829986474)],+                               n = 23},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersecthh:mm", -3.044522437723423),+                                    ("on <date>hh:mm", -3.044522437723423),+                                    ("minuteminute", -1.252762968495368),+                                    ("<day-of-month> (ordinal)<day-of-month> (ordinal)",+                                     -2.639057329615259),+                                    ("hh:mmhh:mm", -1.791759469228055),+                                    ("dayday", -2.128231705849268),+                                    ("<named-month> <day-of-month> (non ordinal)<named-month> <day-of-month> (non ordinal)",+                                     -2.639057329615259),+                                    ("intersect by 'of', 'from', 'shh:mm", -2.3513752571634776)],+                               n = 15},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> (ordinal)<day-of-month>(ordinal) <named-month>",+                                     -2.0794415416798357),+                                    ("daymonth", -2.0794415416798357),+                                    ("dayday", -1.5686159179138452),+                                    ("<day-of-month> (ordinal)intersect", -2.0794415416798357),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -2.0794415416798357)],+                               n = 6}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.8266785731844679),+                                    ("hh:mmhh:mm", -0.8266785731844679)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.8266785731844679),+                                    ("minutehour", -0.8266785731844679)],+                               n = 6}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.9318256327243257,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.5257286443082556),+                                    ("integer (0..19)year (grain)", -2.8134107167600364),+                                    ("integer (numeric)day (grain)", -3.2188758248682006),+                                    ("second", -2.8134107167600364),+                                    ("integer (numeric)second (grain)", -3.2188758248682006),+                                    ("integer (numeric)year (grain)", -3.2188758248682006),+                                    ("day", -2.5257286443082556), ("year", -2.5257286443082556),+                                    ("integer (numeric)week (grain)", -2.8134107167600364),+                                    ("integer (0..19)month (grain)", -2.8134107167600364),+                                    ("integer (0..19)second (grain)", -3.2188758248682006),+                                    ("month", -2.5257286443082556),+                                    ("integer (numeric)minute (grain)", -3.2188758248682006),+                                    ("integer (0..19)minute (grain)", -3.2188758248682006),+                                    ("integer (numeric)month (grain)", -3.2188758248682006),+                                    ("minute", -2.8134107167600364),+                                    ("integer (0..19)day (grain)", -2.8134107167600364),+                                    ("integer (0..19)week (grain)", -3.2188758248682006)],+                               n = 16},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.9444389791664407,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> after <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..19th)named-dayintersect",+                                     -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..19th)named-daychristmas",+                                     -0.916290731874155)],+                               n = 1}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 15},+                   koData =+                     ClassData{prior = -2.772588722239781, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.540445040947149),+                                    ("week (grain)named-month", -1.9459101490553135),+                                    ("day (grain)intersect", -1.9459101490553135),+                                    ("weekmonth", -1.540445040947149),+                                    ("day (grain)named-month", -1.9459101490553135),+                                    ("week (grain)intersect", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -1.6094379124341003),+                                    ("time-of-day (latent)", -1.6094379124341003),+                                    ("hour", -1.0498221244986778)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day>  o'clock", -2.3025850929940455),+                                    ("intersect", -2.3025850929940455),+                                    ("day", -1.6094379124341003),+                                    ("time-of-day (latent)", -2.3025850929940455),+                                    ("hh:mm", -2.3025850929940455), ("hour", -1.8971199848858813),+                                    ("christmas", -1.8971199848858813),+                                    ("minute", -2.3025850929940455)],+                               n = 6}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.916290731874155),+                                    ("at <time-of-day>integer (numeric)", -2.0149030205422647),+                                    ("<time-of-day>  o'clockinteger (numeric)",+                                     -1.0986122886681098)],+                               n = 5},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (0..19)", -1.5040773967762742),+                                    ("time-of-day (latent)integer (numeric)", -1.5040773967762742),+                                    ("hour", -1.0986122886681098)],+                               n = 2}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -1.466337068793427), ("day", -1.1786549963416462),+                                    ("named-day", -1.8718021769015913),+                                    ("hour", -1.8718021769015913),+                                    ("week-end", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/EN.hs view
@@ -0,0 +1,2133 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.EN (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<integer> to|till|before <hour-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.791759469228055, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)noon|midnight|EOD|end of day",+                                     -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.1823215567939546, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7731898882334817),+                                    ("integer (numeric)time-of-day (latent)", -0.7731898882334817)],+                               n = 5}}),+       ("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.7047480922384253),+                                    ("<time-of-day> am|pm", -1.7047480922384253),+                                    ("hh:mm", -1.7047480922384253), ("hour", -1.2992829841302609),+                                    ("minute", -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Thursday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.840653317668535, unseen = -5.030437921392435,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 151},+                   koData =+                     ClassData{prior = -0.5646283297589669, unseen = -5.303304908059076,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 199}}),+       ("<duration> hence|ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.784189633918261,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.563975538357343), ("day", -1.8152899666382492),+                                    ("year", -2.662587827025453),+                                    ("<integer> <unit-of-duration>", -1.0531499145913523),+                                    ("a <unit-of-duration>", -2.662587827025453),+                                    ("month", -2.662587827025453),+                                    ("fortnight", -2.662587827025453)],+                               n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon|midnight|EOD|end of day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter to|till|before <hour-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon|midnight|EOD|end of day", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Father's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> after|before <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("day (grain)tomorrow", -1.6094379124341003),+                                    ("dayday", -1.0986122886681098),+                                    ("day (grain)yesterday", -1.6094379124341003)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.466337068793427),+                                    ("year (grain)Christmas", -1.8718021769015913),+                                    ("day (grain)intersect", -1.466337068793427),+                                    ("yearday", -1.8718021769015913)],+                               n = 3}}),+       ("Martin Luther King's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer after|past <hour-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8109302162163288),+                                    ("integer (numeric)time-of-day (latent)", -1.0986122886681098),+                                    ("integer (20..90)time-of-day (latent)", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal or number) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)February", -1.6094379124341003),+                                    ("integer (numeric)April", -1.6094379124341003),+                                    ("month", -1.2039728043259361)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)August", -1.791759469228055),+                                    ("ordinal (digits)April", -1.791759469228055),+                                    ("month", -1.0986122886681098),+                                    ("integer (numeric)July", -1.791759469228055)],+                               n = 3}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -4.382026634673881,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> (ordinal)in|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("dayhour", -1.5968591302272404),+                                    ("Mondayearly morning", -3.270835563798912),+                                    ("time-of-day (latent)tonight", -3.270835563798912),+                                    ("hourhour", -2.2900063107871858),+                                    ("<time-of-day> o'clockin|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("todaypart of days", -3.676300671907076),+                                    ("minutehour", -2.5776883832389665),+                                    ("at <time-of-day>in|during the <part-of-day>",+                                     -3.270835563798912),+                                    ("time-of-day (latent)this <part-of-day>", -3.676300671907076),+                                    ("Mondayin|during the <part-of-day>", -3.676300671907076),+                                    ("intersectpart of days", -3.676300671907076),+                                    ("intersectin|during the <part-of-day>", -3.676300671907076),+                                    ("<day-of-month> (ordinal or number) of <named-month>in|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("the <day-of-month> (ordinal)in|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("tomorrowpart of days", -2.5776883832389665),+                                    ("hh:mmin|during the <part-of-day>", -2.9831534913471307),+                                    ("time-of-day (latent)in|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("hhmm (latent)in|during the <part-of-day>",+                                     -3.676300671907076),+                                    ("yesterdaypart of days", -3.676300671907076),+                                    ("Mondaypart of days", -3.676300671907076)],+                               n = 27},+                   koData =+                     ClassData{prior = -2.3025850929940455,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -2.740840023925201),+                                    ("monthhour", -2.740840023925201),+                                    ("hourhour", -2.740840023925201),+                                    ("past year (latent)in|during the <part-of-day>",+                                     -2.740840023925201),+                                    ("Februaryin|during the <part-of-day>", -2.740840023925201),+                                    ("time-of-day (latent)in|during the <part-of-day>",+                                     -2.740840023925201)],+                               n = 3}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = -1.6739764335716716,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.2076393647782445, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.10919929196499197,+                               unseen = -4.7535901911063645,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon|midnight|EOD|end of day", -3.6463198396951406),+                                    ("integer after|past <hour-of-day>", -3.6463198396951406),+                                    ("half after|past <hour-of-day>", -4.051784947803305),+                                    ("time-of-day (latent)", -1.8004931491968097),+                                    ("hhmm (latent)", -3.3586377672433594),+                                    ("<time-of-day> am|pm", -1.749199854809259),+                                    ("hh:mm", -3.1354942159291497),+                                    ("about|exactly <time-of-day>", -3.6463198396951406),+                                    ("hour", -1.16141318990714),+                                    ("<time-of-day> sharp|exactly", -4.051784947803305),+                                    ("minute", -1.8545603704670852)],+                               n = 52},+                   koData =+                     ClassData{prior = -2.268683541318364, unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.1895840668738362),+                                    ("hour", -1.1895840668738362)],+                               n = 6}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -2.1972245773362196),+                                    ("Wednesday", -2.6026896854443837),+                                    ("Saturday", -2.6026896854443837),+                                    ("Monday", -2.1972245773362196),+                                    ("Friday", -1.9095425048844386), ("day", -0.8979415932059586),+                                    ("Sunday", -2.6026896854443837)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("September",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the ides of <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("March", -0.6931471805599453), ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("Thursday", -1.791759469228055), ("mm/dd", -3.295836866004329),+                                    ("absorption of , after named day", -2.890371757896165),+                                    ("intersect", -2.890371757896165),+                                    ("Saturday", -2.6026896854443837),+                                    ("Friday", -3.295836866004329), ("day", -0.8979415932059586),+                                    ("the <day-of-month> (ordinal)", -2.890371757896165),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"",+                                     -2.6026896854443837),+                                    ("hour", -3.295836866004329)],+                               n = 22},+                   koData =+                     ClassData{prior = -1.8718021769015913,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.791759469228055), ("day", -1.2809338454620642),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"",+                                     -1.791759469228055)],+                               n = 4}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -2.7398974188114388e-2,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36},+                   koData =+                     ClassData{prior = -3.6109179126442243,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.916290731874155),+                                    ("hh:mmhh:mm", -0.916290731874155)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.916290731874155),+                                    ("minutehour", -0.916290731874155)],+                               n = 3}}),+       ("Halloween",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("October",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> more <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)minute (grain)", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in|within|after <duration>",+        Classifier{okData =+                     ClassData{prior = -5.129329438755058e-2,+                               unseen = -4.532599493153256,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.1354942159291497),+                                    ("<integer> more <unit-of-duration>", -3.828641396489095),+                                    ("three-quarters of an hour", -2.91235066461494),+                                    ("<integer> + '\"", -3.1354942159291497),+                                    ("number.number hours", -3.828641396489095),+                                    ("second", -3.4231762883809305), ("day", -3.1354942159291497),+                                    ("half an hour", -2.91235066461494),+                                    ("<integer> <unit-of-duration>", -1.749199854809259),+                                    ("a <unit-of-duration>", -2.91235066461494),+                                    ("quarter of an hour", -2.91235066461494),+                                    ("hour", -2.4423470353692043),+                                    ("about|exactly <duration>", -3.828641396489095),+                                    ("<integer> and an half hour", -3.828641396489095),+                                    ("minute", -1.3437347467010947)],+                               n = 38},+                   koData =+                     ClassData{prior = -2.995732273553991, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter", -1.8971199848858813),+                                    ("<integer> <unit-of-duration>", -2.3025850929940455),+                                    ("a <unit-of-duration>", -2.3025850929940455)],+                               n = 2}}),+       ("three-quarters of an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Wednesday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half after|past <hour-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> + '\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half <integer> (UK style hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("July",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.8209805520698302,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -0.579818495252942, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.1786549963416462),+                                    ("ordinals (first..twentieth,thirtieth,...)quarter (grain)",+                                     -1.466337068793427),+                                    ("quarter", -0.7731898882334817)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -0.8109302162163288),+                                    ("quarter", -0.8109302162163288)],+                               n = 3}}),+       ("one twenty two",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)integer (numeric)", 0.0)],+                               n = 1}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.44313061099463913,+                               unseen = -6.1092475827643655,+                               likelihoods =+                                 HashMap.fromList+                                   [("<datetime> - <datetime> (interval)on <date>",+                                     -4.497584975308154),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.497584975308154),+                                    ("hourday", -3.709127614943884),+                                    ("dayhour", -3.162583908575814),+                                    ("daymonth", -5.413875707182309),+                                    ("monthday", -5.0084105990741445),+                                    ("monthyear", -3.8044377947482086),+                                    ("Tuesdaythe <day-of-month> (ordinal)", -5.413875707182309),+                                    ("Christmasyear", -5.413875707182309),+                                    ("this|next <day-of-week>hh(:mm) - <time-of-day> am|pm",+                                     -5.413875707182309),+                                    ("<time-of-day> am|pmintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -4.720728526622364),+                                    ("<time-of-day> am|pmintersect", -4.161112738686941),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"year",+                                     -5.413875707182309),+                                    ("Marchyear", -5.413875707182309),+                                    ("<named-month>|<named-day> <day-of-month> (ordinal)year",+                                     -5.0084105990741445),+                                    ("intersect<time-of-day> am|pm", -5.413875707182309),+                                    ("Thursdayhh(:mm) - <time-of-day> am|pm", -5.413875707182309),+                                    ("monthhour", -5.0084105990741445),+                                    ("last <day-of-week> of <time>year", -5.413875707182309),+                                    ("todayat <time-of-day>", -5.413875707182309),+                                    ("Thursday<time> timezone", -5.0084105990741445),+                                    ("this <time>hh(:mm) - <time-of-day> am|pm",+                                     -5.413875707182309),+                                    ("dayday", -3.398972686640044),+                                    ("Thanksgiving Dayyear", -5.0084105990741445),+                                    ("<time> <part-of-day>at <time-of-day>", -5.413875707182309),+                                    ("Tuesdayin <named-month>", -5.413875707182309),+                                    ("mm/ddat <time-of-day>", -5.413875707182309),+                                    ("tonightat <time-of-day>", -5.413875707182309),+                                    ("<time-of-day> am|pmabsorption of , after named day",+                                     -4.720728526622364),+                                    ("today<time-of-day> am|pm", -5.413875707182309),+                                    ("Februarythe <day-of-month> (ordinal)", -5.0084105990741445),+                                    ("at <time-of-day><time> <part-of-day>", -5.413875707182309),+                                    ("mm/dd<time-of-day> am|pm", -5.413875707182309),+                                    ("hourhour", -4.161112738686941),+                                    ("<time-of-day> am|pmon <date>", -3.398972686640044),+                                    ("Wednesdaythis|last|next <cycle>", -5.413875707182309),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -3.909798310406035),+                                    ("dayyear", -3.2166511298460896),+                                    ("<time-of-day> o'clockin|during the <part-of-day>",+                                     -5.413875707182309),+                                    ("<time-of-day> am|pmtomorrow", -4.720728526622364),+                                    ("minutehour", -4.497584975308154),+                                    ("Mother's Dayyear", -5.413875707182309),+                                    ("at <time-of-day>in|during the <part-of-day>",+                                     -5.0084105990741445),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -3.709127614943884),+                                    ("tomorrow<time-of-day> sharp|exactly", -5.413875707182309),+                                    ("Thursdayfrom <datetime> - <datetime> (interval)",+                                     -4.497584975308154),+                                    ("on <date><named-month> <day-of-month> (non ordinal)",+                                     -5.0084105990741445),+                                    ("Thursdayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.497584975308154),+                                    ("Mondayin|during the <part-of-day>", -5.413875707182309),+                                    ("tomorrowfrom <time-of-day> - <time-of-day> (interval)",+                                     -5.0084105990741445),+                                    ("intersectin|during the <part-of-day>", -5.413875707182309),+                                    ("<day-of-month> (ordinal or number) of <named-month>in|during the <part-of-day>",+                                     -5.413875707182309),+                                    ("from <time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.720728526622364),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"<time-of-day> am|pm",+                                     -4.497584975308154),+                                    ("at <time-of-day>intersect", -5.0084105990741445),+                                    ("<time-of-day> - <time-of-day> (interval)tomorrow",+                                     -5.413875707182309),+                                    ("at <time-of-day>intersect by \",\", \"of\", \"from\", \"'s\"",+                                     -5.413875707182309),+                                    ("dayminute", -3.1112906141882632),+                                    ("from <datetime> - <datetime> (interval)on <date>",+                                     -5.0084105990741445),+                                    ("<datetime> - <datetime> (interval)tomorrow",+                                     -5.413875707182309),+                                    ("absorption of , after named dayintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -5.0084105990741445),+                                    ("<ordinal> <cycle> of <time>year", -5.413875707182309),+                                    ("minuteday", -2.0126783255201537),+                                    ("absorption of , after named dayintersect",+                                     -5.413875707182309),+                                    ("Octoberyear", -4.161112738686941),+                                    ("the <day-of-month> (ordinal)in|during the <part-of-day>",+                                     -5.413875707182309),+                                    ("at <time-of-day>absorption of , after named day",+                                     -5.413875707182309),+                                    ("<day-of-month> (ordinal or number) <named-month>year",+                                     -5.413875707182309),+                                    ("year<time-of-day> am|pm", -5.413875707182309),+                                    ("Septemberyear", -5.0084105990741445),+                                    ("at <time-of-day>on <date>", -4.315263418514199),+                                    ("between <time-of-day> and <time-of-day> (interval)on <date>",+                                     -4.720728526622364),+                                    ("Halloweenyear", -5.413875707182309),+                                    ("dayweek", -5.413875707182309),+                                    ("weekyear", -5.0084105990741445),+                                    ("hh:mmin|during the <part-of-day>", -4.720728526622364),+                                    ("Father's Dayyear", -5.413875707182309),+                                    ("<cycle> after|before <time><time-of-day> am|pm",+                                     -5.0084105990741445),+                                    ("February<time> <part-of-day>", -5.413875707182309),+                                    ("Martin Luther King's Dayyear", -5.0084105990741445),+                                    ("tomorrowat <time-of-day>", -4.720728526622364),+                                    ("between <time> and <time>on <date>", -4.720728526622364),+                                    ("at <time-of-day>tomorrow", -5.0084105990741445),+                                    ("tomorrow<time-of-day> am|pm", -5.413875707182309),+                                    ("in|during the <part-of-day>at <time-of-day>",+                                     -5.413875707182309),+                                    ("Labor Dayyear", -5.413875707182309),+                                    ("Februaryintersect", -5.413875707182309),+                                    ("last <cycle> of <time>year", -4.720728526622364),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -5.413875707182309),+                                    ("yearminute", -5.413875707182309)],+                               n = 165},+                   koData =+                     ClassData{prior = -1.0272875078461794, unseen = -5.717027701406222,+                               likelihoods =+                                 HashMap.fromList+                                   [("in <named-month>year", -5.020585624949423),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -5.020585624949423),+                                    ("hourday", -5.020585624949423),+                                    ("<named-month> <day-of-month> (non ordinal)July",+                                     -5.020585624949423),+                                    ("dayhour", -3.228826155721369),+                                    ("daymonth", -3.005682604407159),+                                    ("monthday", -4.61512051684126),+                                    ("monthyear", -4.61512051684126),+                                    ("intersecthh:mm", -5.020585624949423),+                                    ("until <time-of-day><time-of-day> am|pm", -5.020585624949423),+                                    ("<time-of-day> am|pmintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -4.327438444389479),+                                    ("<time-of-day> am|pmintersect", -3.767822656454056),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"year",+                                     -4.327438444389479),+                                    ("Tuesdayafter <time-of-day>", -5.020585624949423),+                                    ("July<day-of-month> (ordinal or number) <named-month>",+                                     -5.020585624949423),+                                    ("absorption of , after named dayJuly", -4.61512051684126),+                                    ("monthhour", -4.61512051684126),+                                    ("todayat <time-of-day>", -5.020585624949423),+                                    ("dayday", -5.020585624949423),+                                    ("mm/ddat <time-of-day>", -4.61512051684126),+                                    ("<time-of-day> am|pmon <date>", -3.767822656454056),+                                    ("dayyear", -4.104294893075269),+                                    ("Thursdayat <time-of-day>", -5.020585624949423),+                                    ("August<time-of-day> am|pm", -5.020585624949423),+                                    ("monthminute", -5.020585624949423),+                                    ("<time-of-day> am|pmtomorrow", -5.020585624949423),+                                    ("Thursdayhh:mm", -5.020585624949423),+                                    ("August<day-of-month> (ordinal or number) <named-month>",+                                     -5.020585624949423),+                                    ("minutemonth", -3.5165082281731497),+                                    ("Thursdayfrom <datetime> - <datetime> (interval)",+                                     -4.61512051684126),+                                    ("Thursdayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.61512051684126),+                                    ("Aprilyear", -5.020585624949423),+                                    ("mm/dd<time-of-day> - <time-of-day> (interval)",+                                     -4.61512051684126),+                                    ("tomorrowfrom <time-of-day> - <time-of-day> (interval)",+                                     -5.020585624949423),+                                    ("yesterday<time-of-day> am|pm", -5.020585624949423),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"hh:mm",+                                     -4.104294893075269),+                                    ("<named-month> <day-of-month> (non ordinal)August",+                                     -5.020585624949423),+                                    ("until <time-of-day>on <date>", -4.327438444389479),+                                    ("at <time-of-day>intersect", -4.61512051684126),+                                    ("at <time-of-day>intersect by \",\", \"of\", \"from\", \"'s\"",+                                     -5.020585624949423),+                                    ("dayminute", -3.0746754758941104),+                                    ("intersectSeptember", -3.5165082281731497),+                                    ("absorption of , after named dayintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -5.020585624949423),+                                    ("minuteday", -2.217225244042889),+                                    ("absorption of , after named dayintersect",+                                     -5.020585624949423),+                                    ("Februaryin|during the <part-of-day>", -5.020585624949423),+                                    ("yearhh:mm", -5.020585624949423),+                                    ("hh:mmon <date>", -3.5165082281731497),+                                    ("absorption of , after named daySeptember",+                                     -4.104294893075269),+                                    ("on <date>September", -4.61512051684126),+                                    ("at <time-of-day>on <date>", -4.61512051684126),+                                    ("absorption of , after named dayFebruary", -4.104294893075269),+                                    ("July<integer> to|till|before <hour-of-day>",+                                     -5.020585624949423),+                                    ("tomorrowat <time-of-day>", -5.020585624949423),+                                    ("tomorrow<time-of-day> am|pm", -5.020585624949423),+                                    ("after <time-of-day><time-of-day> am|pm", -5.020585624949423),+                                    ("after <time-of-day>year", -5.020585624949423),+                                    ("yearminute", -5.020585624949423)],+                               n = 92}}),+       ("after lunch/work/school",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("early morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <number> (implicit minutes)",+        Classifier{okData =+                     ClassData{prior = -1.3217558399823195,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2231435513142097),+                                    ("integer (0..19)", -1.6094379124341003)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.3101549283038396,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3448404862917295),+                                    ("integer (0..19)", -1.2321436812926323)],+                               n = 22}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -2.0149030205422647),+                                    ("quarteryear", -2.0149030205422647),+                                    ("ordinals (first..twentieth,thirtieth,...)day (grain)October",+                                     -2.0149030205422647),+                                    ("ordinals (first..twentieth,thirtieth,...)week (grain)intersect",+                                     -2.0149030205422647),+                                    ("weekmonth", -1.6094379124341003),+                                    ("ordinal (digits)quarter (grain)year", -2.0149030205422647),+                                    ("ordinals (first..twentieth,thirtieth,...)week (grain)October",+                                     -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.4816045409242156),+                                    ("hh:mmhh:mm", -1.4816045409242156),+                                    ("<time-of-day> am|pmtime-of-day (latent)",+                                     -2.3978952727983707),+                                    ("hourhour", -1.9924301646902063),+                                    ("<time-of-day> am|pm<time-of-day> am|pm",+                                     -2.3978952727983707)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.5596157879354228, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.6486586255873816),+                                    ("minuteminute", -2.159484249353372),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.5649493574615367),+                                    ("hourhour", -2.159484249353372),+                                    ("minutehour", -1.6486586255873816),+                                    ("hh:mmintersect", -2.159484249353372),+                                    ("time-of-day (latent)<time-of-day> am|pm",+                                     -2.5649493574615367)],+                               n = 8}}),+       ("Saturday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("week (grain)<named-month>|<named-day> <day-of-month> (ordinal)",+                                     -1.7346010553881064),+                                    ("weekmonth", -1.7346010553881064),+                                    ("week (grain)October", -1.7346010553881064),+                                    ("week (grain)<named-month> <day-of-month> (non ordinal)",+                                     -1.7346010553881064),+                                    ("weekday", -1.2237754316221157)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6359887667199967,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.6094379124341003),+                                    ("hh:mmhh:mm", -1.6094379124341003),+                                    ("<time-of-day> am|pmtime-of-day (latent)", -2.70805020110221),+                                    ("hourhour", -2.3025850929940455),+                                    ("hourminute", -2.3025850929940455),+                                    ("time-of-day (latent)<time-of-day> sharp|exactly",+                                     -2.70805020110221),+                                    ("time-of-day (latent)hh:mm", -2.70805020110221),+                                    ("<time-of-day> am|pm<time-of-day> am|pm", -2.70805020110221)],+                               n = 9},+                   koData =+                     ClassData{prior = -0.7537718023763802, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.540445040947149),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.2335922215070942),+                                    ("hourhour", -1.9459101490553135),+                                    ("minutehour", -1.540445040947149),+                                    ("time-of-day (latent)<time-of-day> am|pm",+                                     -2.639057329615259)],+                               n = 8}}),+       ("integer 21..99",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)integer (numeric)", 0.0)],+                               n = 2}}),+       ("last|next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.430816798843313,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.627081138568543),+                                    ("integer (0..19)year (grain)", -3.3202283191284883),+                                    ("integer (numeric)day (grain)", -3.0325462466767075),+                                    ("integer (0..19)second (grain) ", -3.3202283191284883),+                                    ("integer (0..19)hour (grain)", -3.3202283191284883),+                                    ("second", -2.8094026953624978),+                                    ("integer (numeric)second (grain) ", -3.3202283191284883),+                                    ("integer (numeric)year (grain)", -3.3202283191284883),+                                    ("day", -2.472930458741285), ("year", -2.8094026953624978),+                                    ("integer (numeric)week (grain)", -3.0325462466767075),+                                    ("integer (0..19)month (grain)", -3.3202283191284883),+                                    ("hour", -2.8094026953624978), ("month", -2.8094026953624978),+                                    ("integer (numeric)minute (grain)", -3.3202283191284883),+                                    ("integer (0..19)minute (grain)", -3.3202283191284883),+                                    ("integer (numeric)month (grain)", -3.3202283191284883),+                                    ("minute", -2.8094026953624978),+                                    ("integer (numeric)hour (grain)", -3.3202283191284883),+                                    ("integer (0..19)day (grain)", -3.0325462466767075),+                                    ("integer (0..19)week (grain)", -3.3202283191284883)],+                               n = 31},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Memorial Day",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("Monday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinal (digits)quarter (grain)year", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("about|exactly <time-of-day>integer (numeric)",+                                     -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.9808292530117262),+                                    ("ordinals (first..twentieth,thirtieth,...)Tuesdayintersect",+                                     -2.0794415416798357),+                                    ("ordinals (first..twentieth,thirtieth,...)Wednesdayintersect",+                                     -1.6739764335716716),+                                    ("ordinals (first..twentieth,thirtieth,...)TuesdayOctober",+                                     -1.6739764335716716)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.0986122886681098),+                                    ("ordinals (first..twentieth,thirtieth,...)TuesdaySeptember",+                                     -1.791759469228055),+                                    ("ordinals (first..twentieth,thirtieth,...)WednesdayOctober",+                                     -1.3862943611198906)],+                               n = 3}}),+       ("Valentine's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("April",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("end of month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = -2.7398974188114388e-2,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36},+                   koData =+                     ClassData{prior = -3.6109179126442243,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<part-of-day> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("part of daysintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -1.6094379124341003),+                                    ("hourday", -0.916290731874155),+                                    ("part of daysthe <day-of-month> (ordinal)",+                                     -1.6094379124341003),+                                    ("part of daysthe <day-of-month> (number)",+                                     -1.6094379124341003)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("past year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal or number) of <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)July", -2.3513752571634776),+                                    ("ordinals (first..twentieth,thirtieth,...)March",+                                     -2.3513752571634776),+                                    ("ordinal (digits)February", -2.3513752571634776),+                                    ("integer (numeric)February", -1.9459101490553135),+                                    ("month", -0.9650808960435872),+                                    ("ordinal (digits)March", -2.3513752571634776),+                                    ("integer (numeric)July", -2.3513752571634776)],+                               n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)February", -1.5040773967762742),+                                    ("month", -1.5040773967762742)],+                               n = 1}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("part of days", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Friday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("early morning", -2.5257286443082556),+                                    ("hour", -0.7339691750802004),+                                    ("part of days", -0.8209805520698302)],+                               n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.916290731874155),+                                    ("part of days", -0.916290731874155)],+                               n = 1}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh(:mm) - <time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this|last|next <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.11122563511022437,+                               unseen = -4.3694478524670215,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5234954826333758),+                                    ("month (grain)", -2.9704144655697013),+                                    ("year (grain)", -1.8718021769015913),+                                    ("week (grain)", -1.5234954826333758),+                                    ("quarter", -2.7472709142554916), ("year", -1.8718021769015913),+                                    ("month", -2.9704144655697013),+                                    ("quarter (grain)", -2.7472709142554916)],+                               n = 34},+                   koData =+                     ClassData{prior = -2.2512917986064953,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("week (grain)", -1.791759469228055),+                                    ("day", -1.791759469228055),+                                    ("day (grain)", -1.791759469228055)],+                               n = 4}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("New Year's Eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinal (digits)quarter (grain)year", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon|midnight|EOD|end of day", -2.1972245773362196),+                                    ("end of month", -2.1972245773362196),+                                    ("time-of-day (latent)", -2.1972245773362196),+                                    ("<time-of-day> am|pm", -2.1972245773362196),+                                    ("hh:mm", -2.1972245773362196), ("hour", -1.791759469228055),+                                    ("month", -2.1972245773362196), ("minute", -1.791759469228055)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.2006706954621511,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..twentieth,thirtieth,...)",+                                     -1.7047480922384253),+                                    ("ordinal (digits)", -0.2006706954621511)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.7047480922384253,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList [("ordinal (digits)", -0.2876820724517809)],+                               n = 2}}),+       ("the <day-of-month> (number)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Sunday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("February",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 1}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.6330432564902398, unseen = -4.143134726391533,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.10178269430994236),+                                    ("integer (0..19)", -2.3353749158170367)],+                               n = 60},+                   koData =+                     ClassData{prior = -0.7570959051602187, unseen = -4.02535169073515,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.15718558352241238),+                                    ("integer (0..19)", -1.927891643552635)],+                               n = 53}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -3.4011973816621555,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 28},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 7}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.916290731874155),+                                    ("SundayMarch", -1.6094379124341003),+                                    ("MondayMarch", -1.6094379124341003),+                                    ("Sundayintersect", -1.6094379124341003)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.8209805520698302, unseen = -4.499809670330265,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.2914117923959205),+                                    ("integer (0..19)year (grain)", -3.1023420086122493),+                                    ("integer (numeric)day (grain)", -2.5427262206768266),+                                    ("integer (0..19)second (grain) ", -3.7954891891721947),+                                    ("integer (0..19)hour (grain)", -2.6968769005040847),+                                    ("second", -3.7954891891721947),+                                    ("integer (numeric)year (grain)", -3.7954891891721947),+                                    ("day", -2.5427262206768266), ("year", -2.8791984572980396),+                                    ("integer (numeric)week (grain)", -2.8791984572980396),+                                    ("integer (0..19)month (grain)", -3.39002408106403),+                                    ("hour", -2.409194828052304), ("month", -3.39002408106403),+                                    ("integer (numeric)minute (grain)", -2.8791984572980396),+                                    ("integer (0..19)minute (grain)", -3.7954891891721947),+                                    ("minute", -2.6968769005040847),+                                    ("integer (numeric)hour (grain)", -3.39002408106403),+                                    ("integer (0..19)week (grain)", -2.8791984572980396)],+                               n = 33},+                   koData =+                     ClassData{prior = -0.579818495252942, unseen = -4.68213122712422,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.8810693652338513),+                                    ("integer (0..19)year (grain)", -3.5742165457937967),+                                    ("integer (numeric)day (grain)", -3.2865344733420154),+                                    ("integer (0..19)second (grain) ", -3.5742165457937967),+                                    ("integer (0..19)hour (grain)", -3.5742165457937967),+                                    ("second", -3.0633909220278057),+                                    ("integer (numeric)second (grain) ", -3.5742165457937967),+                                    ("integer (numeric)year (grain)", -3.5742165457937967),+                                    ("day", -2.7269186854065928), ("quarter", -3.979681653901961),+                                    ("year", -3.0633909220278057),+                                    ("integer (numeric)week (grain)", -3.2865344733420154),+                                    ("integer (0..19)month (grain)", -3.5742165457937967),+                                    ("hour", -1.9647786333596962), ("month", -3.0633909220278057),+                                    ("integer (numeric)minute (grain)", -3.5742165457937967),+                                    ("integer (0..19)minute (grain)", -3.5742165457937967),+                                    ("integer (numeric)month (grain)", -3.5742165457937967),+                                    ("minute", -3.0633909220278057),+                                    ("integer (numeric)hour (grain)", -2.1078794770003695),+                                    ("integer (0..19)day (grain)", -3.2865344733420154),+                                    ("integer (0..19)week (grain)", -3.5742165457937967),+                                    ("integer (0..19)quarter (grain)", -3.979681653901961)],+                               n = 42}}),+       ("hhmm (latent)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.29354719190417905,+                               unseen = -5.231108616854587,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer after|past <hour-of-day>", -3.8394523125933104),+                                    ("at <time-of-day>", -2.2300144001592104),+                                    ("<time-of-day> o'clock", -4.127134385045092),+                                    ("half after|past <hour-of-day>", -4.127134385045092),+                                    ("time-of-day (latent)", -1.7600107709134747),+                                    ("hhmm (latent)", -4.532599493153256),+                                    ("hh:mm", -2.181224235989778),+                                    ("quarter after|past <hour-of-day>", -4.532599493153256),+                                    ("about|exactly <time-of-day>", -4.532599493153256),+                                    ("until <time-of-day>", -3.8394523125933104),+                                    ("hour", -1.2939210409888755),+                                    ("<time-of-day> sharp|exactly", -4.532599493153256),+                                    ("minute", -1.6422277352570913),+                                    ("after <time-of-day>", -4.532599493153256)],+                               n = 85},+                   koData =+                     ClassData{prior = -1.3689026184080213, unseen = -4.31748811353631,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> to|till|before <hour-of-day>", -3.20545280453606),+                                    ("<hour-of-day> <integer>", -3.6109179126442243),+                                    ("time-of-day (latent)", -1.0459685551826876),+                                    ("hour", -1.0082282271998406), ("minute", -2.917770732084279),+                                    ("after <time-of-day>", -3.6109179126442243)],+                               n = 29}}),+       ("Thanksgiving Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.6286086594223742,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.0149030205422647),+                                    ("year (grain)", -2.70805020110221),+                                    ("second", -2.70805020110221),+                                    ("week (grain)", -2.0149030205422647),+                                    ("day", -2.3025850929940455),+                                    ("minute (grain)", -2.70805020110221),+                                    ("year", -2.70805020110221),+                                    ("second (grain) ", -2.70805020110221),+                                    ("minute", -2.70805020110221),+                                    ("day (grain)", -2.3025850929940455)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.7621400520468967, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour (grain)", -1.7227665977411035),+                                    ("quarter", -1.9459101490553135), ("hour", -1.7227665977411035),+                                    ("quarter (grain)", -1.9459101490553135)],+                               n = 7}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -5.406722127027582e-2,+                               unseen = -4.02535169073515,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 54},+                   koData =+                     ClassData{prior = -2.9444389791664407,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("quarter of an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain) ",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (first..twentieth,thirtieth,...)",+        Classifier{okData =+                     ClassData{prior = -6.899287148695143e-2,+                               unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -2.70805020110221, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <hour-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> after|before <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("day (grain)tomorrow", -1.252762968495368),+                                    ("dayday", -0.8472978603872037),+                                    ("day (grain)yesterday", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about|exactly <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6026896854443837),+                                    ("hh(:mm) - <time-of-day> am|pm", -2.6026896854443837),+                                    ("this|last|next <cycle>", -2.6026896854443837),+                                    ("day", -2.1972245773362196),+                                    ("time-of-day (latent)", -2.6026896854443837),+                                    ("hhmm (latent)", -2.1972245773362196),+                                    ("<time-of-day> am|pm", -2.6026896854443837),+                                    ("hour", -1.9095425048844386),+                                    ("next <time>", -2.6026896854443837),+                                    ("this|next <day-of-week>", -2.6026896854443837),+                                    ("minute", -2.1972245773362196)],+                               n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.8718021769015913),+                                    ("hour", -1.8718021769015913)],+                               n = 1}}),+       ("intersect by \",\", \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = -0.41773520069997866,+                               unseen = -5.1298987149230735,+                               likelihoods =+                                 HashMap.fromList+                                   [("Wednesday<named-month> <day-of-month> (non ordinal)",+                                     -4.430816798843313),+                                    ("dayhour", -3.1780538303479458),+                                    ("daymonth", -3.1780538303479458),+                                    ("<named-month> <day-of-month> (non ordinal)Friday",+                                     -4.430816798843313),+                                    ("Friday<named-month> <day-of-month> (non ordinal)",+                                     -3.7376696182833684),+                                    ("Wednesdayintersect", -4.430816798843313),+                                    ("Labor Daythis|last|next <cycle>", -4.430816798843313),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"year",+                                     -4.430816798843313),+                                    ("<part-of-day> of <time>February", -4.430816798843313),+                                    ("Saturday<time-of-day> am|pm", -4.430816798843313),+                                    ("Martin Luther King's Daythis|last|next <cycle>",+                                     -4.430816798843313),+                                    ("on <date><time-of-day> am|pm", -4.430816798843313),+                                    ("hourmonth", -4.430816798843313),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"intersect",+                                     -4.430816798843313),+                                    ("dayday", -2.559014621941722),+                                    ("the <day-of-month> (ordinal)February", -4.02535169073515),+                                    ("WednesdayOctober", -4.430816798843313),+                                    ("Wednesdaythis|last|next <cycle>", -4.02535169073515),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -3.5145260669691587),+                                    ("dayyear", -2.9267394020670396),+                                    ("Saturday<named-month> <day-of-month> (non ordinal)",+                                     -4.430816798843313),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -4.430816798843313),+                                    ("Thursdayhh:mm", -4.02535169073515),+                                    ("Thanksgiving Daythis|last|next <cycle>", -4.430816798843313),+                                    ("Memorial Daythis|last|next <cycle>", -4.430816798843313),+                                    ("on <date><named-month> <day-of-month> (non ordinal)",+                                     -4.02535169073515),+                                    ("TuesdayOctober", -4.430816798843313),+                                    ("the <day-of-month> (ordinal)March", -4.430816798843313),+                                    ("Mondaythis|last|next <cycle>", -4.430816798843313),+                                    ("Fridayintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -4.02535169073515),+                                    ("Fridayintersect", -4.430816798843313),+                                    ("Thursday<datetime> - <datetime> (interval)",+                                     -3.7376696182833684),+                                    ("Thursday<time-of-day> - <time-of-day> (interval)",+                                     -3.5145260669691587),+                                    ("Tuesdaythis|last|next <cycle>", -4.430816798843313),+                                    ("Sunday<named-month> <day-of-month> (non ordinal)",+                                     -4.430816798843313),+                                    ("dayminute", -2.639057329615259),+                                    ("intersectyear", -4.430816798843313),+                                    ("minuteday", -3.5145260669691587),+                                    ("this|last|next <cycle>Sunday", -4.430816798843313),+                                    ("Sundaythis|last|next <cycle>", -4.430816798843313),+                                    ("intersectintersect", -4.430816798843313),+                                    ("weekday", -4.430816798843313),+                                    ("dayweek", -3.332204510175204),+                                    ("Thursday<time-of-day> am|pm", -4.430816798843313),+                                    ("Monday<named-month> <day-of-month> (non ordinal)",+                                     -4.02535169073515),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -4.02535169073515)],+                               n = 54},+                   koData =+                     ClassData{prior = -1.074514737089049, unseen = -4.762173934797756,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.8632184332102),+                                    ("TuesdaySeptember", -4.060443010546419),+                                    ("Wednesdayintersect", -4.060443010546419),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"intersect",+                                     -4.060443010546419),+                                    ("SundayFebruary", -4.060443010546419),+                                    ("WednesdayOctober", -4.060443010546419),+                                    ("FridayJuly", -3.654977902438255),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -4.060443010546419),+                                    ("FridaySeptember", -4.060443010546419),+                                    ("WednesdayFebruary", -4.060443010546419),+                                    ("minutemonth", -3.144152278672264),+                                    ("SundayMarch", -4.060443010546419),+                                    ("Fridayintersect by \",\", \"of\", \"from\", \"'s\"",+                                     -4.060443010546419),+                                    ("MondayFebruary", -3.654977902438255),+                                    ("Fridayintersect", -4.060443010546419),+                                    ("Thursday<time-of-day> - <time-of-day> (interval)",+                                     -3.654977902438255),+                                    ("dayminute", -2.6741486494265287),+                                    ("SaturdaySeptember", -4.060443010546419),+                                    ("intersectSeptember", -3.144152278672264),+                                    ("MondayMarch", -4.060443010546419),+                                    ("on <date>September", -3.654977902438255),+                                    ("intersectintersect", -4.060443010546419),+                                    ("Tuesdayintersect", -4.060443010546419),+                                    ("Sundayintersect", -4.060443010546419)],+                               n = 28}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -1.2729656758128873, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("Father's Day", -2.5649493574615367),+                                    ("Martin Luther King's Day", -2.5649493574615367),+                                    ("Memorial Day", -2.5649493574615367),+                                    ("Mother's Day", -2.5649493574615367),+                                    ("day", -1.3121863889661687), ("Sunday", -2.5649493574615367),+                                    ("hour", -2.5649493574615367), ("Tuesday", -2.5649493574615367),+                                    ("week-end", -2.5649493574615367)],+                               n = 7},+                   koData =+                     ClassData{prior = -0.3285040669720361, unseen = -3.891820298110627,+                               likelihoods =+                                 HashMap.fromList+                                   [("Monday", -3.1780538303479458), ("day", -2.2617630984737906),+                                    ("Sunday", -3.1780538303479458),+                                    ("time-of-day (latent)", -1.1631508098056809),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"",+                                     -2.772588722239781),+                                    ("hour", -1.1631508098056809)],+                               n = 18}}),+       ("March",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month>|<named-day> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("Octoberordinal (digits)", -1.9459101490553135),+                                    ("Thursdayordinal (digits)", -2.3513752571634776),+                                    ("day", -1.9459101490553135),+                                    ("Marchordinals (first..twentieth,thirtieth,...)",+                                     -1.9459101490553135),+                                    ("Tuesdayordinal (digits)", -2.3513752571634776),+                                    ("month", -1.252762968495368),+                                    ("Marchordinal (digits)", -2.3513752571634776)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Labor Day weekend",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("ordinal (digits)", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.9808292530117262, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -2.3025850929940455),+                                    ("<time-of-day> am|pm", -1.6094379124341003),+                                    ("hh:mm", -1.8971199848858813), ("hour", -1.8971199848858813),+                                    ("minute", -1.3862943611198906)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.4700036292457356, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.7227665977411035),+                                    ("yesterday", -2.2335922215070942),+                                    ("day", -2.2335922215070942), ("hh:mm", -1.7227665977411035),+                                    ("hour", -2.639057329615259), ("minute", -1.252762968495368)],+                               n = 10}}),+       ("<duration> after|before|from <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("a <unit-of-duration>now", -2.3513752571634776),+                                    ("a <unit-of-duration>Christmas", -2.3513752571634776),+                                    ("<integer> <unit-of-duration>today", -2.3513752571634776),+                                    ("secondsecond", -2.3513752571634776),+                                    ("daysecond", -2.3513752571634776),+                                    ("<integer> <unit-of-duration>Christmas", -2.3513752571634776),+                                    ("yearday", -1.6582280766035324),+                                    ("minutesecond", -2.3513752571634776),+                                    ("<integer> <unit-of-duration>now", -1.9459101490553135)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Independence Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("decimal number",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("Martin Luther King's Day", -2.803360380906535),+                                    ("Halloween", -2.803360380906535),+                                    ("Wednesday", -2.803360380906535),+                                    ("Memorial Day", -2.803360380906535),+                                    ("Monday", -2.803360380906535),+                                    ("Mother's Day", -2.803360380906535),+                                    ("day", -1.0986122886681098),+                                    ("Thanksgiving Day", -2.803360380906535),+                                    ("March", -2.803360380906535), ("month", -2.803360380906535),+                                    ("Tuesday", -2.1102132003465894)],+                               n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> sharp|exactly",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -2.1400661634962708),+                                    ("time-of-day (latent)", -2.1400661634962708),+                                    ("hhmm (latent)", -2.1400661634962708),+                                    ("<time-of-day> am|pm", -2.1400661634962708),+                                    ("hh:mm", -2.1400661634962708), ("hour", -1.7346010553881064),+                                    ("minute", -1.4469189829363254)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Memorial Day Weekend",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("negative numbers",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 18}}),+       ("about|exactly <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> before last|after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("Wednesday", -1.8718021769015913),+                                    ("Friday", -1.466337068793427), ("day", -1.1786549963416462),+                                    ("March", -1.8718021769015913), ("month", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by the end of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("this|last|next <cycle>", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hhmm (military) am|pm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.48550781578170077,+                               unseen = -3.891820298110627,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.4733057381095205),+                                    ("hh:mmhh:mm", -1.6739764335716716),+                                    ("dayday", -2.772588722239781),+                                    ("hourhour", -2.2617630984737906),+                                    ("<named-month> <day-of-month> (non ordinal)<named-month> <day-of-month> (non ordinal)",+                                     -2.772588722239781),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"hh:mm",+                                     -2.772588722239781),+                                    ("intersect by \",\", \"of\", \"from\", \"'s\"<time-of-day> am|pm",+                                     -3.1780538303479458),+                                    ("<time-of-day> am|pm<time-of-day> am|pm",+                                     -2.4849066497880004)],+                               n = 16},+                   koData =+                     ClassData{prior = -0.9555114450274363,+                               unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("<named-month> <day-of-month> (non ordinal)July",+                                     -2.890371757896165),+                                    ("daymonth", -2.4849066497880004),+                                    ("<time-of-day> am|pmintersect", -2.890371757896165),+                                    ("hh:mm<time-of-day> am|pm", -2.4849066497880004),+                                    ("minuteminute", -1.9740810260220096),+                                    ("hourhour", -2.4849066497880004),+                                    ("minutehour", -2.4849066497880004),+                                    ("hh:mmintersect", -1.9740810260220096),+                                    ("<named-month> <day-of-month> (non ordinal)August",+                                     -2.890371757896165),+                                    ("about|exactly <time-of-day><time-of-day> am|pm",+                                     -2.890371757896165)],+                               n = 10}}),+       ("Tuesday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("New Year's Day",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("fortnight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> and an half hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("October", -1.252762968495368), ("March", -1.252762968495368),+                                    ("month", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("October", -0.916290731874155), ("month", -0.916290731874155)],+                               n = 1}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8873031950009028,+                               unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.5163474893680884),+                                    ("hh:mmhh:mm", -1.5163474893680884),+                                    ("<time-of-day> am|pmtime-of-day (latent)", -2.327277705584417),+                                    ("hourhour", -1.7676619176489945),+                                    ("<time-of-day> am|pm<time-of-day> am|pm", -2.327277705584417)],+                               n = 14},+                   koData =+                     ClassData{prior = -0.5306282510621704,+                               unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("about|exactly <time-of-day>time-of-day (latent)",+                                     -3.2771447329921766),+                                    ("hh:mmtime-of-day (latent)", -1.5723966407537513),+                                    ("hh:mm<time-of-day> am|pm", -2.871679624884012),+                                    ("<time-of-day> am|pmtime-of-day (latent)",+                                     -3.2771447329921766),+                                    ("at <time-of-day><time-of-day> am|pm", -3.2771447329921766),+                                    ("hourhour", -2.0243817644968085),+                                    ("minutehour", -1.262241712449912),+                                    ("about|exactly <time-of-day><time-of-day> am|pm",+                                     -3.2771447329921766),+                                    ("at <time-of-day>time-of-day (latent)", -2.871679624884012),+                                    ("<integer> to|till|before <hour-of-day>time-of-day (latent)",+                                     -2.871679624884012)],+                               n = 20}}),+       ("nth <time> after <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..twentieth,thirtieth,...)Tuesdayintersect",+                                     -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..twentieth,thirtieth,...)TuesdayChristmas",+                                     -0.916290731874155)],+                               n = 1}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.25131442828090605,+                               unseen = -3.9318256327243257,+                               likelihoods =+                                 HashMap.fromList+                                   [("Augustinteger (numeric)", -2.5257286443082556),+                                    ("Marchinteger (numeric)", -2.8134107167600364),+                                    ("Aprilinteger (numeric)", -3.2188758248682006),+                                    ("month", -0.8209805520698302),+                                    ("Februaryinteger (numeric)", -1.9661128563728327),+                                    ("Septemberinteger (numeric)", -2.8134107167600364),+                                    ("Octoberinteger (numeric)", -2.8134107167600364),+                                    ("Julyinteger (numeric)", -2.120263536200091)],+                               n = 21},+                   koData =+                     ClassData{prior = -1.5040773967762742, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("Marchinteger (numeric)", -2.3025850929940455),+                                    ("Aprilinteger (numeric)", -2.3025850929940455),+                                    ("month", -1.0498221244986778),+                                    ("Julyinteger (numeric)", -1.3862943611198906)],+                               n = 6}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("Thursday", -2.2512917986064953),+                                    ("Wednesday", -2.2512917986064953),+                                    ("Monday", -1.845826690498331), ("day", -0.8649974374866046),+                                    ("Tuesday", -1.55814461804655)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("day (grain)October", -1.791759469228055),+                                    ("daymonth", -1.2809338454620642),+                                    ("day (grain)intersect", -1.791759469228055),+                                    ("weekmonth", -1.791759469228055),+                                    ("week (grain)intersect", -2.1972245773362196),+                                    ("week (grain)September", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("seasons",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)April", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Labor Day",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.7047480922384253),+                                    ("<time-of-day> am|pm", -1.7047480922384253),+                                    ("hour", -1.2992829841302609)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.03688192726104),+                                    ("tomorrow", -2.03688192726104), ("day", -1.3437347467010947),+                                    ("time-of-day (latent)", -2.4423470353692043),+                                    ("<time-of-day> am|pm", -2.4423470353692043),+                                    ("Christmas", -2.03688192726104), ("hour", -1.749199854809259)],+                               n = 8}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 21},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("between <time> and <time>",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0116009116784799),+                                    ("hh:mmhh:mm", -1.0116009116784799)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.4469189829363254),+                                    ("minuteminute", -1.4469189829363254),+                                    ("minutehour", -1.4469189829363254),+                                    ("hh:mmintersect", -1.4469189829363254)],+                               n = 6}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("July", -0.6931471805599453), ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("part of days",+        Classifier{okData =+                     ClassData{prior = -4.445176257083381e-2,+                               unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -3.1354942159291497,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("Thursday", -2.772588722239781),+                                    ("Martin Luther King's Day", -2.772588722239781),+                                    ("intersect", -2.772588722239781),+                                    ("Monday", -2.772588722239781), ("day", -1.3862943611198906),+                                    ("Thanksgiving Day", -2.772588722239781),+                                    ("hour", -1.8562979903656263), ("seasons", -2.0794415416798357),+                                    ("week-end", -2.772588722239781),+                                    ("part of days", -2.367123614131617)],+                               n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.791759469228055),+                                    ("part of days", -1.791759469228055)],+                               n = 1}}),+       ("August",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/ES.hs view
@@ -0,0 +1,1160 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.ES (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("midnight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.5839478885949533, unseen = -4.0943445622221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 58},+                   koData =+                     ClassData{prior = -0.8157495026522777, unseen = -3.871201010907891,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 46}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh(:|.|h)mm (time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month|named-day> past",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("el <time>", -1.2992829841302609),+                                    ("day", -0.7884573603642702),+                                    ("named-day", -1.2992829841302609)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd[/-]mm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by `de`",+        Classifier{okData =+                     ClassData{prior = -0.16362942378180204,+                               unseen = -4.812184355372417,+                               likelihoods =+                                 HashMap.fromList+                                   [("el <day-of-month> (non ordinal)intersect by `de`",+                                     -3.7054087560651467),+                                    ("day of month (1st)named-month", -3.1945831322991562),+                                    ("daymonth", -1.7594986070098335),+                                    ("monthyear", -3.7054087560651467),+                                    ("named-dayel proximo <cycle> ", -4.110873864173311),+                                    ("named-dayla <cycle> pasado", -4.110873864173311),+                                    ("el <time>named-month", -3.7054087560651467),+                                    ("dayyear", -2.164963715117998),+                                    ("dd-dd <month>(interval)year", -4.110873864173311),+                                    ("el <time>el <cycle> (proximo|que viene)", -4.110873864173311),+                                    ("two time tokens separated by \",\"named-month",+                                     -4.110873864173311),+                                    ("named-monthyear", -3.7054087560651467),+                                    ("el <time>year", -3.7054087560651467),+                                    ("el <time>la <cycle> pasado", -4.110873864173311),+                                    ("el <day-of-month> de <named-month>year", -3.7054087560651467),+                                    ("el <time>este|en un <cycle>", -3.7054087560651467),+                                    ("named-dayel <cycle> (proximo|que viene)", -4.110873864173311),+                                    ("el <day-of-month> (non ordinal)named-month",+                                     -2.406125771934886),+                                    ("<day-of-month> de <named-month>year", -3.7054087560651467),+                                    ("two time tokens separated by \",\"year", -3.417726683613366),+                                    ("two time tokens separated by \",\"intersect by `de`",+                                     -4.110873864173311),+                                    ("dayweek", -2.406125771934886),+                                    ("intersect by `de`year", -3.417726683613366),+                                    ("named-dayeste|en un <cycle>", -3.417726683613366)],+                               n = 45},+                   koData =+                     ClassData{prior = -1.890850371872286, unseen = -3.891820298110627,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthyear", -3.1780538303479458),+                                    ("hourmonth", -2.772588722239781),+                                    ("monthmonth", -3.1780538303479458),+                                    ("a las <time-of-day>named-month", -2.772588722239781),+                                    ("dayyear", -3.1780538303479458),+                                    ("minutemonth", -2.772588722239781),+                                    ("named-monthyear", -3.1780538303479458),+                                    ("de <datetime> - <datetime> (interval)named-month",+                                     -3.1780538303479458),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -3.1780538303479458),+                                    ("<day-of-month> de <named-month>year", -3.1780538303479458),+                                    ("intersect by `de`year", -3.1780538303479458),+                                    ("<hour-of-day> <integer> (as relative minutes)intersect by `de`",+                                     -3.1780538303479458),+                                    ("minuteyear", -3.1780538303479458)],+                               n = 8}}),+       ("n pasados <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..15)a\241o (grain)", -1.3862943611198906),+                                    ("year", -1.3862943611198906),+                                    ("number (0..15)mes (grain)", -1.3862943611198906),+                                    ("month", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> and half",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.3217558399823195),+                                    ("time-of-day (latent)", -1.3217558399823195),+                                    ("hour", -0.7621400520468967)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("pasados n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.4849066497880004),+                                    ("integer (numeric)dia (grain)", -2.4849066497880004),+                                    ("integer (numeric)mes (grain)", -2.4849066497880004),+                                    ("second", -2.4849066497880004),+                                    ("integer (numeric)minutos (grain)", -2.4849066497880004),+                                    ("day", -2.4849066497880004),+                                    ("integer (numeric)segundo (grain)", -2.4849066497880004),+                                    ("year", -2.4849066497880004), ("month", -2.4849066497880004),+                                    ("minute", -2.4849066497880004),+                                    ("integer (numeric)a\241o (grain)", -2.4849066497880004),+                                    ("number (0..15)semana (grain)", -2.4849066497880004)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("semana (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two time tokens separated by \",\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayel <time>", -2.159484249353372),+                                    ("dayday", -0.8602012652231115),+                                    ("named-dayel <day-of-month> (non ordinal)",+                                     -2.5649493574615367),+                                    ("named-dayintersect by `de`", -1.466337068793427),+                                    ("named-day<day-of-month> de <named-month>",+                                     -2.5649493574615367),+                                    ("named-dayel <day-of-month> de <named-month>",+                                     -2.5649493574615367)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> de la manana",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.3217558399823195),+                                    ("time-of-day (latent)", -1.3217558399823195),+                                    ("hour", -0.7621400520468967)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("del mediod\237a",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> de <named-month>",+        Classifier{okData =+                     ClassData{prior = -9.53101798043249e-2,+                               unseen = -3.784189633918261,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..15)named-month", -2.151762203259462),+                                    ("integer (numeric)named-month", -0.9279867716373464),+                                    ("month", -0.7166776779701395)],+                               n = 20},+                   koData =+                     ClassData{prior = -2.3978952727983707,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.8472978603872037),+                                    ("month", -0.8472978603872037)],+                               n = 2}}),+       ("<time-of-day> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3528213746227423, unseen = -4.31748811353631,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> de <named-month>in the <part-of-day>",+                                     -3.6109179126442243),+                                    ("dayhour", -2.2246235515243336),+                                    ("tomorrowin the <part-of-day>", -3.6109179126442243),+                                    ("a las <time-of-day>del mediod\237a", -3.6109179126442243),+                                    ("el <day-of-month> de <named-month>in the <part-of-day>",+                                     -3.6109179126442243),+                                    ("hourhour", -2.2246235515243336),+                                    ("a las <time-of-day>in the <part-of-day>",+                                     -2.3581549441488563),+                                    ("intersectin the <part-of-day>", -3.6109179126442243),+                                    ("minutehour", -1.739115735742633),+                                    ("intersect by `de`in the <part-of-day>", -3.6109179126442243),+                                    ("<hour-of-day> and halfin the <part-of-day>",+                                     -3.20545280453606),+                                    ("named-dayin the <part-of-day>", -3.6109179126442243),+                                    ("<hour-of-day> and <relative minutes>del mediod\237a",+                                     -3.20545280453606),+                                    ("el <time>in the <part-of-day>", -3.6109179126442243),+                                    ("<hour-of-day> and quarterin the <part-of-day>",+                                     -2.6946271807700692),+                                    ("yesterdayin the <part-of-day>", -3.6109179126442243),+                                    ("time-of-day (latent)in the <part-of-day>",+                                     -2.917770732084279)],+                               n = 26},+                   koData =+                     ClassData{prior = -1.213022639845854, unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -1.4816045409242156),+                                    ("year (latent)del mediod\237a", -3.0910424533583156),+                                    ("monthhour", -3.0910424533583156),+                                    ("hourhour", -3.0910424533583156),+                                    ("named-monthin the <part-of-day>", -3.0910424533583156),+                                    ("year (latent)in the <part-of-day>", -1.5869650565820417),+                                    ("time-of-day (latent)in the <part-of-day>",+                                     -3.0910424533583156)],+                               n = 11}}),+       ("de <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.791759469228055),+                                    ("monthyear", -1.791759469228055),+                                    ("monthhour", -1.791759469228055),+                                    ("named-monthyear (latent)", -1.791759469228055),+                                    ("named-monthtime-of-day (latent)", -1.791759469228055),+                                    ("named-month<day-of-month> de <named-month>",+                                     -1.791759469228055)],+                               n = 3}}),+       ("<time-of-day> horas",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.252762968495368),+                                    ("time-of-day (latent)", -1.252762968495368),+                                    ("hour", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.7884573603642702),+                                    ("hour", -0.7884573603642702)],+                               n = 4}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.2578291093020998,+                               unseen = -4.6443908991413725,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> de <named-month>in the <part-of-day>",+                                     -3.9415818076696905),+                                    ("dayhour", -1.9956716586143772),+                                    ("tomorrowin the <part-of-day>", -3.9415818076696905),+                                    ("el <day-of-month> de <named-month>in the <part-of-day>",+                                     -3.9415818076696905),+                                    ("hourhour", -3.0252910757955354),+                                    ("now<hour-of-day> minus quarter (as relative minutes)",+                                     -3.9415818076696905),+                                    ("dayyear", -3.0252910757955354),+                                    ("a las <time-of-day>in the <part-of-day>",+                                     -2.6888188391743224),+                                    ("intersectin the <part-of-day>", -3.9415818076696905),+                                    ("<named-month> <day-of-month>del <year>", -3.9415818076696905),+                                    ("minutehour", -2.33214389523559),+                                    ("intersect by `de`in the <part-of-day>", -3.9415818076696905),+                                    ("now<hour-of-day> and <relative minutes>",+                                     -3.9415818076696905),+                                    ("<hour-of-day> and halfin the <part-of-day>",+                                     -3.536116699561526),+                                    ("named-dayin the <part-of-day>", -3.9415818076696905),+                                    ("tomorrowa las <time-of-day>", -3.536116699561526),+                                    ("named-daya las <time-of-day>", -3.9415818076696905),+                                    ("named-dayintersect", -3.9415818076696905),+                                    ("dayminute", -3.0252910757955354),+                                    ("<named-month> <day-of-month>el <time>", -3.9415818076696905),+                                    ("named-day<dim time> de la manana", -3.9415818076696905),+                                    ("el <time>in the <part-of-day>", -3.9415818076696905),+                                    ("named-day<time-of-day> <part-of-day>", -3.9415818076696905),+                                    ("dd[/-]mmyear", -3.536116699561526),+                                    ("nowa las <time-of-day>", -3.536116699561526),+                                    ("<hour-of-day> and quarterin the <part-of-day>",+                                     -3.0252910757955354),+                                    ("yesterdayin the <part-of-day>", -3.9415818076696905)],+                               n = 34},+                   koData =+                     ClassData{prior = -1.4816045409242156, unseen = -4.02535169073515,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -3.3141860046725258),+                                    ("dayhour", -2.6210388241125804),+                                    ("<day-of-month> de <named-month>a las <time-of-day>",+                                     -3.3141860046725258),+                                    ("<time-of-day> am|pm<day-of-month> de <named-month>",+                                     -3.3141860046725258),+                                    ("monthhour", -2.908720896564361),+                                    ("now<hour-of-day> and <relative minutes>",+                                     -3.3141860046725258),+                                    ("dayminute", -2.908720896564361),+                                    ("named-monthin the <part-of-day>", -3.3141860046725258),+                                    ("named-montha las <time-of-day>", -3.3141860046725258),+                                    ("nowa las <time-of-day>", -2.6210388241125804),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -2.908720896564361),+                                    ("minuteyear", -2.908720896564361)],+                               n = 10}}),+       ("a las <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -8.338160893905101e-2,+                               unseen = -4.634728988229636,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> and half", -3.2386784521643803),+                                    ("<time-of-day> horas", -3.9318256327243257),+                                    ("<hour-of-day> and quarter", -3.0155349008501706),+                                    ("time-of-day (latent)", -1.2237754316221157),+                                    ("<hour-of-day> and <relative minutes>", -2.833213344056216),+                                    ("<time-of-day> am|pm", -3.9318256327243257),+                                    ("<hour-of-day> minus <integer> (as relative minutes)",+                                     -3.9318256327243257),+                                    ("<hour-of-day> minus quarter (as relative minutes)",+                                     -3.5263605246161616),+                                    ("hour", -1.1592369104845446), ("minute", -1.8523840910444898)],+                               n = 46},+                   koData =+                     ClassData{prior = -2.5257286443082556,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.791759469228055),+                                    ("<hour-of-day> and <relative minutes>", -1.791759469228055),+                                    ("hour", -1.791759469228055), ("minute", -1.791759469228055)],+                               n = 4}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minutos (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.1786549963416462),+                                    ("number (0..15)", -0.6190392084062235),+                                    ("number (20..90)", -1.8718021769015913)],+                               n = 10}}),+       ("el <cycle> (proximo|que viene)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("semana (grain)", -1.540445040947149),+                                    ("mes (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135),+                                    ("a\241o (grain)", -1.9459101490553135),+                                    ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> and quarter",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.4350845252893227),+                                    ("time-of-day (latent)", -1.252762968495368),+                                    ("hour", -0.7419373447293773)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dentro de <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hace <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8718021769015913), ("year", -1.8718021769015913),+                                    ("<integer> <unit-of-duration>", -0.9555114450274363),+                                    ("hour", -1.8718021769015913), ("month", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("el <day-of-month> de <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..15)named-month", -1.749199854809259),+                                    ("integer (numeric)named-month", -1.0560526742493137),+                                    ("month", -0.7375989431307791)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 25},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("el <time>",+        Classifier{okData =+                     ClassData{prior = -5.406722127027582e-2,+                               unseen = -4.465908118654584,+                               likelihoods =+                                 HashMap.fromList+                                   [("<named-month|named-day> past", -3.355735007585398),+                                    ("dd[/-]mm", -3.068052935133617),+                                    ("intersect by `de`", -2.257122718917288),+                                    ("<day-of-month> de <named-month>", -2.056452023455137),+                                    ("<time-of-day> <part-of-day>", -3.7612001156935624),+                                    ("intersect", -3.7612001156935624),+                                    ("day", -0.9279867716373464), ("year", -3.7612001156935624),+                                    ("named-day", -2.374905754573672),+                                    ("day of month (1st)", -3.355735007585398),+                                    ("<named-month|named-day> next", -3.7612001156935624),+                                    ("hour", -3.355735007585398)],+                               n = 36},+                   koData =+                     ClassData{prior = -2.9444389791664407, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -2.2512917986064953), ("hour", -2.2512917986064953),+                                    ("minute", -2.2512917986064953),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -2.2512917986064953)],+                               n = 2}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (primero..10)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("evening", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (0..15)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.9318256327243257,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 49},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("este|en un <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.0296194171811581),+                                    ("semana (grain)", -1.0296194171811581),+                                    ("year", -1.9459101490553135),+                                    ("a\241o (grain)", -1.9459101490553135)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2006706954621511),+                                    ("number (0..15)", -1.7047480922384253)],+                               n = 9}}),+       ("dd-dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -1.0116009116784799, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("mes (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-week> <day-of-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayinteger (numeric)", -0.6931471805599453),+                                    ("day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.3272129112084162,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.1939224684724346),+                                    ("number (0..15)", -0.3610133455373305)],+                               n = 31},+                   koData =+                     ClassData{prior = -1.276293465905562, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3364722366212129),+                                    ("number (0..15)", -1.252762968495368)],+                               n = 12}}),+       ("<hour-of-day> and <relative minutes>",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+                                     -2.1972245773362196),+                                    ("time-of-day (latent)number (0..15)", -2.6026896854443837),+                                    ("a las <time-of-day>number (20..90)", -2.1972245773362196),+                                    ("a las <time-of-day>number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+                                     -2.1972245773362196),+                                    ("hour", -0.8979415932059586),+                                    ("a las <time-of-day>number (0..15)", -2.6026896854443837),+                                    ("time-of-day (latent)number (20..90)", -2.1972245773362196)],+                               n = 10},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>number (20..90)", -1.6094379124341003),+                                    ("hour", -1.0986122886681098),+                                    ("time-of-day (latent)number (20..90)", -1.6094379124341003)],+                               n = 4}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 3}}),+       ("en <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9444389791664407), ("second", -2.9444389791664407),+                                    ("day", -2.538973871058276), ("year", -2.538973871058276),+                                    ("<integer> <unit-of-duration>", -0.8649974374866046),+                                    ("hour", -2.2512917986064953), ("month", -2.9444389791664407),+                                    ("minute", -1.845826690498331)],+                               n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n <cycle> (proximo|que viene)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("integer (numeric)semana (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055),+                                    ("number (0..15)mes (grain)", -1.791759469228055),+                                    ("month", -1.791759469228055),+                                    ("integer (numeric)a\241o (grain)", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -4.143134726391533,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.028522096376982),+                                    ("integer (numeric)hora (grain)", -3.4339872044851463),+                                    ("integer (numeric)dia (grain)", -3.4339872044851463),+                                    ("number (0..15)segundo (grain)", -3.4339872044851463),+                                    ("second", -3.4339872044851463),+                                    ("number (0..15)a\241o (grain)", -3.028522096376982),+                                    ("integer (numeric)minutos (grain)", -2.740840023925201),+                                    ("day", -3.028522096376982), ("year", -2.740840023925201),+                                    ("number (0..15)mes (grain)", -3.028522096376982),+                                    ("number (0..15)hora (grain)", -2.740840023925201),+                                    ("hour", -2.3353749158170367), ("month", -3.028522096376982),+                                    ("number (0..15)dia (grain)", -3.4339872044851463),+                                    ("number (0..15)minutos (grain)", -3.028522096376982),+                                    ("number (16..19 21..29)hora (grain)", -3.4339872044851463),+                                    ("minute", -2.3353749158170367),+                                    ("integer (numeric)a\241o (grain)", -3.4339872044851463),+                                    ("number (0..15)semana (grain)", -3.028522096376982)],+                               n = 20},+                   koData =+                     ClassData{prior = -0.8109302162163288, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.890371757896165),+                                    ("integer (numeric)hora (grain)", -2.890371757896165),+                                    ("integer (numeric)dia (grain)", -2.890371757896165),+                                    ("integer (numeric)mes (grain)", -3.295836866004329),+                                    ("second", -2.890371757896165),+                                    ("number (0..15)a\241o (grain)", -3.295836866004329),+                                    ("integer (numeric)semana (grain)", -3.295836866004329),+                                    ("integer (numeric)minutos (grain)", -2.890371757896165),+                                    ("day", -2.890371757896165),+                                    ("integer (numeric)segundo (grain)", -2.890371757896165),+                                    ("year", -2.6026896854443837),+                                    ("number (0..15)mes (grain)", -2.890371757896165),+                                    ("hour", -2.890371757896165), ("month", -2.6026896854443837),+                                    ("minute", -2.890371757896165),+                                    ("integer (numeric)a\241o (grain)", -2.890371757896165),+                                    ("number (0..15)semana (grain)", -3.295836866004329)],+                               n = 16}}),+       ("proximas n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)hora (grain)", -2.4849066497880004),+                                    ("integer (numeric)dia (grain)", -2.4849066497880004),+                                    ("second", -2.4849066497880004),+                                    ("number (0..15)a\241o (grain)", -2.4849066497880004),+                                    ("integer (numeric)minutos (grain)", -2.4849066497880004),+                                    ("day", -2.4849066497880004),+                                    ("integer (numeric)segundo (grain)", -2.4849066497880004),+                                    ("year", -2.4849066497880004),+                                    ("number (0..15)mes (grain)", -2.4849066497880004),+                                    ("hour", -2.4849066497880004), ("month", -2.4849066497880004),+                                    ("minute", -2.4849066497880004)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.252762968495368),+                                    ("time-of-day (latent)", -1.252762968495368),+                                    ("hour", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("n proximas <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("integer (numeric)mes (grain)", -1.791759469228055),+                                    ("integer (numeric)semana (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055), ("month", -1.791759469228055),+                                    ("integer (numeric)a\241o (grain)", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ano nuevo",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("la <cycle> pasado",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2039728043259361),+                                    ("semana (grain)", -1.2039728043259361),+                                    ("year", -1.6094379124341003),+                                    ("a\241o (grain)", -1.6094379124341003)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("la pasado <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("mes (grain)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4657359027997265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 30},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList [("number (20..90)number (0..15)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day of month (1st)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a\241o (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> minus <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)number (0..15)", -1.252762968495368),+                                    ("hour", -0.8472978603872037),+                                    ("a las <time-of-day>number (0..15)", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month|named-day> next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("el <time>", -1.5040773967762742),+                                    ("day", -0.8109302162163288),+                                    ("named-day", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (16..19 21..29)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> de la tarde",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> and half", -2.5902671654458267),+                                    ("a las <time-of-day>", -1.6094379124341003),+                                    ("<hour-of-day> and quarter", -2.0794415416798357),+                                    ("time-of-day (latent)", -2.0794415416798357),+                                    ("hour", -1.491654876777717), ("minute", -1.3862943611198906)],+                               n = 17},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("el proximo <cycle> ",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("semana (grain)", -1.540445040947149),+                                    ("mes (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135),+                                    ("a\241o (grain)", -1.9459101490553135),+                                    ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> minus quarter (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("a las <time-of-day>", -1.2992829841302609),+                                    ("time-of-day (latent)", -1.2992829841302609),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("del <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd[/-.]mm[/-.]yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.252762968495368, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.9459101490553135),+                                    ("dayday", -1.9459101490553135),+                                    ("hh(:|.|h)mm (time-of-day)hh(:|.|h)mm (time-of-day)",+                                     -1.9459101490553135),+                                    ("<day-of-month> de <named-month><day-of-month> de <named-month>",+                                     -1.9459101490553135)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.3364722366212129, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -2.3025850929940455),+                                    ("dayyear", -1.8971199848858813),+                                    ("named-month<day-of-month> de <named-month>",+                                     -2.3025850929940455),+                                    ("dd[/-]mmyear", -1.8971199848858813),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -1.8971199848858813),+                                    ("minuteyear", -1.8971199848858813)],+                               n = 5}}),+       ("el <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2682639865946794),+                                    ("number (0..15)", -1.4469189829363254)],+                               n = 15},+                   koData =+                     ClassData{prior = -2.772588722239781, unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)", -0.40546510810816444)],+                               n = 1}}),+       ("segundo (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dia (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3101549283038396, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -1.466337068793427),+                                    ("hour", -0.7731898882334817), ("evening", -2.159484249353372),+                                    ("morning", -1.6486586255873816)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.3217558399823195,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -1.3862943611198906),+                                    ("hour", -0.8754687373538999),+                                    ("morning", -1.3862943611198906)],+                               n = 4}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Nochevieja",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hora (grain)",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("right now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Navidad",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 5}}),+       ("ce <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -1.6094379124341003), ("day", -1.3217558399823195),+                                    ("named-day", -2.0149030205422647),+                                    ("hour", -1.6094379124341003),+                                    ("week-end", -1.6094379124341003)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/ET.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.ET (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/FR.hs view
@@ -0,0 +1,2395 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.FR (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("n derniers <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.803360380906535),+                                    ("number (0..16)seconde (grain)", -2.803360380906535),+                                    ("number (0..16)jour (grain)", -2.803360380906535),+                                    ("second", -2.3978952727983707),+                                    ("integer (numeric)ann\233e (grain)", -2.803360380906535),+                                    ("integer (numeric)seconde (grain)", -2.803360380906535),+                                    ("number (0..16)minute (grain)", -2.803360380906535),+                                    ("integer (numeric)jour (grain)", -2.803360380906535),+                                    ("day", -2.3978952727983707), ("year", -2.803360380906535),+                                    ("month", -2.803360380906535),+                                    ("integer (numeric)minute (grain)", -2.803360380906535),+                                    ("integer (numeric)mois (grain)", -2.803360380906535),+                                    ("minute", -2.3978952727983707),+                                    ("integer (numeric)semaine (grain)", -2.803360380906535)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> prochain",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2}}),+       ("du|dans le <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2657031657330056, unseen = -4.07753744390572,+                               likelihoods =+                                 HashMap.fromList+                                   [("soir", -2.114532861491106),+                                    ("fin de journ\233e", -3.367295829986474),+                                    ("fin de matin\233e", -3.367295829986474),+                                    ("d\233but de soir\233e", -3.367295829986474),+                                    ("d\233but de matin\233e", -3.367295829986474),+                                    ("apr\232s-midi", -2.9618307218783095),+                                    ("d\233but de journ\233e", -3.367295829986474),+                                    ("matin", -2.114532861491106), ("hour", -0.8823891801984737),+                                    ("fin de soir\233e", -3.367295829986474),+                                    ("fin d'apr\232s-midi", -2.9618307218783095),+                                    ("d\233but d'apr\232s-midi", -3.367295829986474)],+                               n = 23},+                   koData =+                     ClassData{prior = -1.455287232606842, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("soir", -2.5649493574615367), ("matin", -1.3121863889661687),+                                    ("hour", -1.1786549963416462)],+                               n = 7}}),+       ("dans <duration>",+        Classifier{okData =+                     ClassData{prior = -8.338160893905101e-2,+                               unseen = -4.04305126783455,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.639057329615259),+                                    ("<integer> + '\"", -2.9267394020670396),+                                    ("second", -2.639057329615259), ("day", -2.9267394020670396),+                                    ("year", -2.639057329615259),+                                    ("<integer> <unit-of-duration>", -1.1921383466789333),+                                    ("une <unit-of-duration>", -2.2335922215070942),+                                    ("hour", -2.4159137783010487), ("month", -3.332204510175204),+                                    ("minute", -1.9459101490553135)],+                               n = 23},+                   koData =+                     ClassData{prior = -2.5257286443082556, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9459101490553135), ("day", -1.9459101490553135),+                                    ("une <unit-of-duration>", -1.540445040947149)],+                               n = 2}}),+       ("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>", -1.5040773967762742),+                                    ("hour", -0.8109302162163288),+                                    ("<time-of-day> heures", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n <cycle> apr\232s",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..16)jour (grain)", -0.6931471805599453),+                                    ("day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.500101660403015, unseen = -5.424950017481403,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 225},+                   koData =+                     ClassData{prior = -0.9325954408990987, unseen = -4.997212273764115,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 146}}),+       ("<named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("apr\232s le travail",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n prochains <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.833213344056216),+                                    ("number (0..16)seconde (grain)", -2.833213344056216),+                                    ("second", -2.4277482359480516),+                                    ("integer (numeric)ann\233e (grain)", -2.833213344056216),+                                    ("integer (numeric)seconde (grain)", -2.833213344056216),+                                    ("number (0..16)minute (grain)", -2.833213344056216),+                                    ("integer (numeric)jour (grain)", -2.833213344056216),+                                    ("day", -2.833213344056216), ("year", -2.833213344056216),+                                    ("hour", -2.833213344056216), ("month", -2.833213344056216),+                                    ("integer (numeric)minute (grain)", -2.833213344056216),+                                    ("integer (numeric)mois (grain)", -2.833213344056216),+                                    ("minute", -2.4277482359480516),+                                    ("integer (numeric)semaine (grain)", -2.833213344056216),+                                    ("integer (numeric)heure (grain)", -2.833213344056216)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-week> <day-of-month> \224 <time-of-day>)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -0.7827593392496325),+                                    ("named-dayinteger (numeric)\224|vers <time-of-day>",+                                     -1.6094379124341003),+                                    ("named-daynumber (0..16)<time-of-day> heures",+                                     -2.456735772821304),+                                    ("named-dayinteger (numeric)<time-of-day> heures",+                                     -2.169053700369523),+                                    ("named-daynumber (0..16)\224|vers <time-of-day>",+                                     -1.9459101490553135)],+                               n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("apr\232s le d\233jeuner",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-day> en quinze",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("entre <datetime> et <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.25131442828090605,+                               unseen = -4.127134385045092,+                               likelihoods =+                                 HashMap.fromList+                                   [("le <time>le <day-of-month> (non ordinal)",+                                     -3.417726683613366),+                                    ("le <time>le <time>", -3.012261575505202),+                                    ("dayday", -1.7129785913749407),+                                    ("hourhour", -3.417726683613366),+                                    ("le <time>intersect", -3.417726683613366),+                                    ("miditime-of-day (latent)", -3.417726683613366),+                                    ("intersectle <day-of-month> (non ordinal)",+                                     -3.417726683613366),+                                    ("minutehour", -1.7129785913749407),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -3.012261575505202),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -2.7245795030534206),+                                    ("le <day-of-month> (non ordinal)le <day-of-month> (non ordinal)",+                                     -3.012261575505202),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -2.7245795030534206),+                                    ("intersectintersect", -3.417726683613366),+                                    ("intersectle <time>", -3.012261575505202),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -3.012261575505202)],+                               n = 21},+                   koData =+                     ClassData{prior = -1.5040773967762742,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -2.740840023925201),+                                    ("dayday", -2.3353749158170367),+                                    ("le <day-of-month> (non ordinal)intersect",+                                     -2.740840023925201),+                                    ("minutehour", -1.824549292051046),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -2.740840023925201),+                                    ("le <day-of-month> (non ordinal)le <time>",+                                     -2.740840023925201),+                                    ("hh(:|h)mm (time-of-day)intersect", -2.740840023925201),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -2.740840023925201)],+                               n = 6}}),+       ("soir",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("ann\233e (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("d\233but de semaine",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> moins <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("midinumber (0..16)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month|named-day> suivant|d'apr\232s",+        Classifier{okData =+                     ClassData{prior = -0.10178269430994236,+                               unseen = -4.174387269895637,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.5494451709255714),+                                    ("en semaine", -1.9616585060234524),+                                    ("intersect by 'de' or ','", -2.5494451709255714),+                                    ("day", -0.7915872533731978),+                                    ("named-day", -2.5494451709255714),+                                    ("le <time>", -1.9616585060234524)],+                               n = 28},+                   koData =+                     ClassData{prior = -2.3353749158170367, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("en semaine", -1.9459101490553135),+                                    ("day", -1.540445040947149), ("hour", -1.9459101490553135),+                                    ("<time-of-day> heures", -1.9459101490553135),+                                    ("le <time>", -1.9459101490553135)],+                               n = 3}}),+       ("seconde (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> et|pass\233 de <number>",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>number (20..60)", -2.3513752571634776),+                                    ("<time-of-day> heuresinteger (numeric)", -2.3513752571634776),+                                    ("\224|vers <time-of-day>number (0..16)", -2.3513752571634776),+                                    ("hour", -0.9650808960435872),+                                    ("<time-of-day> heuresnumber (20..60)", -1.9459101490553135),+                                    ("<time-of-day> heuresnumber (0..16)", -1.9459101490553135)],+                               n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("midiinteger (numeric)", -1.5040773967762742),+                                    ("hour", -1.5040773967762742)],+                               n = 1}}),+       ("<hour-of-day> moins quart",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("midi", -0.6931471805599453), ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("de <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)<hour-of-day> <integer> (as relative minutes)",+                                     -2.6855773452501515),+                                    ("minuteminute", -1.5869650565820417),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -3.0910424533583156),+                                    ("<time-of-day> heures<time-of-day> heures",+                                     -3.0910424533583156),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -2.6855773452501515),+                                    ("hourhour", -2.3978952727983707),+                                    ("minutehour", -2.174751721484161),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -2.3978952727983707),+                                    ("<hour-of-day> <integer> (as relative minutes)hh(:|h)mm (time-of-day)",+                                     -2.6855773452501515),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.0910424533583156),+                                    ("<hour-of-day> <integer> (as relative minutes)<hour-of-day> <integer> (as relative minutes)",+                                     -2.6855773452501515),+                                    ("<time-of-day> heurestime-of-day (latent)",+                                     -3.0910424533583156)],+                               n = 15},+                   koData =+                     ClassData{prior = -0.8109302162163288,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("minutehour", -1.072636802264849),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -2.2512917986064953),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -2.538973871058276),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -2.538973871058276),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -1.845826690498331)],+                               n = 12}}),+       ("<datetime>-dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = -1.466337068793427, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.3217558399823195),+                                    ("<day-of-month> <named-month>named-month",+                                     -1.6094379124341003),+                                    ("day of month (premier)named-month", -2.0149030205422647)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.262364264467491, unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourmonth", -1.7578579175523736),+                                    ("named-monthnamed-month", -2.268683541318364),+                                    ("monthmonth", -2.268683541318364),+                                    ("year (latent)named-month", -1.7578579175523736),+                                    ("yearmonth", -1.7578579175523736),+                                    ("time-of-day (latent)named-month", -1.7578579175523736)],+                               n = 10}}),+       ("semaine (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.6635616461296463,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 37},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> + '\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("demain",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -1.0116009116784799, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("mois (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by 'mais/par exemple/plut\244t'",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -2.3978952727983707),+                                    ("named-dayentre <time-of-day> et <time-of-day> (interval)",+                                     -1.5869650565820417),+                                    ("le <day-of-month> (non ordinal)<time-of-day> heures",+                                     -3.0910424533583156),+                                    ("le <day-of-month> (non ordinal)\224|vers <time-of-day>",+                                     -2.6855773452501515),+                                    ("dayminute", -0.9509762898620451),+                                    ("named-dayentre <datetime> et <datetime> (interval)",+                                     -1.5869650565820417)],+                               n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("de <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.410986973710262, unseen = -4.143134726391533,+                               likelihoods =+                                 HashMap.fromList+                                   [("day of month (premier)<day-of-week> <day-of-month>",+                                     -3.4339872044851463),+                                    ("hh(:|h)mm (time-of-day)<hour-of-day> <integer> (as relative minutes)",+                                     -3.4339872044851463),+                                    ("minuteminute", -2.517696472610991),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -3.4339872044851463),+                                    ("dayday", -2.517696472610991),+                                    ("<day-of-month> <named-month>day of month (premier)",+                                     -3.4339872044851463),+                                    ("minutehour", -3.028522096376982),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -3.4339872044851463),+                                    ("<hour-of-day> <integer> (as relative minutes)hh(:|h)mm (time-of-day)",+                                     -3.4339872044851463),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.4339872044851463),+                                    ("<hour-of-day> <integer> (as relative minutes)<hour-of-day> <integer> (as relative minutes)",+                                     -3.4339872044851463),+                                    ("<day-of-month> <named-month>intersect", -3.4339872044851463),+                                    ("intersect<day-of-week> <day-of-month>", -3.4339872044851463)],+                               n = 10},+                   koData =+                     ClassData{prior = -0.27958486221916157,+                               unseen = -4.653960350157523,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -3.951243718581427),+                                    ("<day-of-month> <named-month>time-of-day (latent)",+                                     -3.951243718581427),+                                    ("hourday", -3.0349529867072724),+                                    ("dayhour", -3.951243718581427),+                                    ("yearhour", -3.951243718581427),+                                    ("intersectnamed-day", -3.951243718581427),+                                    ("time-of-day (latent)year (latent)", -3.951243718581427),+                                    ("houryear", -3.951243718581427),+                                    ("day of month (premier)named-day", -3.951243718581427),+                                    ("time-of-day (latent)intersect", -3.545778610473263),+                                    ("year (latent)intersect", -3.545778610473263),+                                    ("yearyear", -3.951243718581427),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -3.951243718581427),+                                    ("dayday", -2.2464956263430023),+                                    ("year (latent)year (latent)", -3.951243718581427),+                                    ("<day-of-week> <day-of-month><day-of-week> <day-of-month>",+                                     -3.951243718581427),+                                    ("hourhour", -3.951243718581427),+                                    ("time-of-day (latent)<day-of-week> <day-of-month>",+                                     -3.951243718581427),+                                    ("minutehour", -2.4471663218051534),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -3.545778610473263),+                                    ("year (latent)<day-of-week> <day-of-month>",+                                     -3.951243718581427),+                                    ("year (latent)time-of-day (latent)", -3.951243718581427),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -3.951243718581427),+                                    ("year (latent)named-day", -3.951243718581427),+                                    ("time-of-day (latent)named-day", -3.951243718581427),+                                    ("day of month (premier)intersect", -3.545778610473263),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.951243718581427),+                                    ("intersectintersect", -3.545778610473263),+                                    ("hh(:|h)mm (time-of-day)intersect", -3.951243718581427),+                                    ("yearday", -3.0349529867072724),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -3.545778610473263),+                                    ("<day-of-week> <day-of-month>named-day", -3.951243718581427),+                                    ("<day-of-week> <day-of-month>intersect", -3.545778610473263)],+                               n = 31}}),+       ("<ordinal> <cycle> de <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7346010553881064),+                                    ("ordinals (premier..seizieme)semaine (grain)named-month",+                                     -1.7346010553881064),+                                    ("ordinal (digits)jour (grain)named-month",+                                     -1.7346010553881064),+                                    ("weekmonth", -1.2237754316221157),+                                    ("ordinals (premier..seizieme)semaine (grain)intersect",+                                     -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("premi\232re quinzaine de <named-month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n <cycle> suivants",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.6094379124341003), ("month", -1.6094379124341003),+                                    ("integer (numeric)mois (grain)", -1.6094379124341003),+                                    ("integer (numeric)heure (grain)", -1.6094379124341003)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..16)jour (grain)", -1.2039728043259361),+                                    ("day", -1.2039728043259361)],+                               n = 2}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.2911008792005665,+                               unseen = -6.9440872082295275,+                               likelihoods =+                                 HashMap.fromList+                                   [("apr\232s <time-of-day>named-month", -5.844510134151319),+                                    ("<day-of-month> <named-month><dim time> <part-of-day>",+                                     -5.844510134151319),+                                    ("intersect<dim time> du matin", -5.844510134151319),+                                    ("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -5.844510134151319),+                                    ("hh(:|h)mm (time-of-day)named-day", -5.844510134151319),+                                    ("demain<time-of-day> heures", -5.844510134151319),+                                    ("hourday", -4.640537329825383),+                                    ("<day-of-month> <named-month>year", -5.556828061699537),+                                    ("dayhour", -1.6960983506589422),+                                    ("daymonth", -3.0719214119115374),+                                    ("monthyear", -4.745897845483209),+                                    ("dernier <cycle> de <time> (latent)year", -5.333684510385328),+                                    ("named-month<dim time> du matin", -5.844510134151319),+                                    ("<day-of-month> <named-month>\224|vers <time-of-day>",+                                     -4.109909078763212),+                                    ("dd mmyear", -4.997212273764115),+                                    ("le <day-of-month> (non ordinal)<dim time> du matin",+                                     -5.844510134151319),+                                    ("hh(:|h)mm (time-of-day)<day-of-week> <day-of-month>",+                                     -6.249975242259483),+                                    ("named-month\224|vers <time-of-day>", -4.997212273764115),+                                    ("named-dayday of month (premier)", -5.556828061699537),+                                    ("<time-of-day> heuresdu|dans le <part-of-day>",+                                     -4.745897845483209),+                                    ("<hour-of-day> et quart<dim time> <part-of-day>",+                                     -5.556828061699537),+                                    ("<day-of-week> <day-of-month>named-month", -5.556828061699537),+                                    ("le <time>du|dans le <part-of-day>", -5.333684510385328),+                                    ("\224|vers <time-of-day>ce <part-of-day>", -5.556828061699537),+                                    ("le <day-of-month> (non ordinal)<dim time> du soir",+                                     -4.997212273764115),+                                    ("entre <datetime> et <datetime> (interval)named-day",+                                     -5.844510134151319),+                                    ("<hour-of-day> et demice <part-of-day>", -5.556828061699537),+                                    ("le <day-of-month> (non ordinal)<time-of-day> heures",+                                     -4.640537329825383),+                                    ("<hour-of-day> <integer> (as relative minutes)<day-of-week> <day-of-month>",+                                     -6.249975242259483),+                                    ("le <day-of-month> (non ordinal)named-month",+                                     -4.2350722217172185),+                                    ("monthhour", -4.1705337005796475),+                                    ("le <time><time-of-day> heures", -5.151362953591374),+                                    ("hourmonth", -5.333684510385328),+                                    ("<time-of-day> heuresle <time>", -5.333684510385328),+                                    ("dayday", -3.898599985096005),+                                    ("aujourd'hui<hour-of-day> <integer> (as relative minutes)",+                                     -5.556828061699537),+                                    ("apr\232s <time-of-day>named-day", -5.844510134151319),+                                    ("named-dayle <cycle> prochain|suivant|d'apr\232s",+                                     -4.863680881139593),+                                    ("named-dayapr\232s <time-of-day>", -5.556828061699537),+                                    ("hourhour", -3.2295503561151206),+                                    ("<day-of-week> <day-of-month>\224|vers <time-of-day>",+                                     -4.5452271500210575),+                                    ("le <time>intersect", -5.556828061699537),+                                    ("\224|vers <time-of-day><dim time> <part-of-day>",+                                     -6.249975242259483),+                                    ("<time-of-day> heuresintersect", -5.844510134151319),+                                    ("intersectnamed-month", -4.997212273764115),+                                    ("intersect<time-of-day> heures", -5.556828061699537),+                                    ("<hour-of-day> et quartce <part-of-day>", -5.556828061699537),+                                    ("dayyear", -3.8520799694611125),+                                    ("named-dayce|dans le <cycle>", -5.556828061699537),+                                    ("apr\232s-demain\224|vers <time-of-day>", -5.333684510385328),+                                    ("le <ordinal> <cycle> de <time>year", -6.249975242259483),+                                    ("demain\224|vers <time-of-day>", -5.333684510385328),+                                    ("le <day-of-month> (non ordinal)intersect",+                                     -3.6472855568150995),+                                    ("hourminute", -6.249975242259483),+                                    ("dd-dd <month>(interval)year", -6.249975242259483),+                                    ("intersect<day-of-month> <named-month>", -5.844510134151319),+                                    ("minutemonth", -5.844510134151319),+                                    ("\224|vers <time-of-day>demain", -6.249975242259483),+                                    ("minutehour", -4.378173065357892),+                                    ("named-daydu|dans le <part-of-day>", -5.556828061699537),+                                    ("named-monthyear", -4.745897845483209),+                                    ("entre <datetime> et <datetime> (interval)named-month",+                                     -6.249975242259483),+                                    ("intersectdu|dans le <part-of-day>", -3.898599985096005),+                                    ("le <day-of-month> \224 <datetime>du|dans le <part-of-day>",+                                     -5.844510134151319),+                                    ("named-month<dim time> <part-of-day>", -5.844510134151319),+                                    ("le <day-of-month> (non ordinal)apr\232s <time-of-day>",+                                     -6.249975242259483),+                                    ("named-day<day-of-month> <named-month>", -5.556828061699537),+                                    ("named-dayle <time>", -4.109909078763212),+                                    ("le <day-of-month> (non ordinal)<dim time> <part-of-day>",+                                     -4.5452271500210575),+                                    ("dd/-mm<time-of-day> heures", -5.844510134151319),+                                    ("de <datetime> - <datetime> (interval)named-month",+                                     -5.844510134151319),+                                    ("apr\232s <time-of-day>le <time>", -5.844510134151319),+                                    ("named-day<time-of-day> heures", -5.556828061699537),+                                    ("<hour-of-day> et quartdemain", -5.556828061699537),+                                    ("<time-of-day> heuresce <time>", -6.249975242259483),+                                    ("<day-of-month> <named-month>du|dans le <part-of-day>",+                                     -5.844510134151319),+                                    ("named-dayintersect", -6.249975242259483),+                                    ("le <time><dim time> du matin", -5.844510134151319),+                                    ("apr\232s <time-of-day>intersect", -6.249975242259483),+                                    ("le <day-of-month> (non ordinal)\224|vers <time-of-day>",+                                     -4.304065093204169),+                                    ("hierdu|dans le <part-of-day>", -6.249975242259483),+                                    ("intersect<dim time> <part-of-day>", -5.844510134151319),+                                    ("dayminute", -4.745897845483209),+                                    ("<ordinal> <cycle> de <time>year", -5.844510134151319),+                                    ("le <time>\224|vers <time-of-day>", -4.5452271500210575),+                                    ("<day-of-month> <named-month><dim time> du matin",+                                     -5.844510134151319),+                                    ("intersectyear", -5.556828061699537),+                                    ("<day-of-week> <day-of-month><time-of-day> heures",+                                     -5.151362953591374),+                                    ("minuteday", -3.279560776689782),+                                    ("<datetime> - <datetime> (interval)named-month",+                                     -4.997212273764115),+                                    ("<day-of-month> <named-month><time-of-day> heures",+                                     -4.745897845483209),+                                    ("aujourd'hui\224|vers <time-of-day>", -5.333684510385328),+                                    ("day of month (premier)intersect", -6.249975242259483),+                                    ("entre <time-of-day> et <time-of-day> (interval)named-day",+                                     -5.844510134151319),+                                    ("named-day<named-month|named-day> suivant|d'apr\232s",+                                     -5.333684510385328),+                                    ("<dim time> <part-of-day>apr\232s <time-of-day>",+                                     -6.249975242259483),+                                    ("named-month<time-of-day> heures", -5.556828061699537),+                                    ("<time-of-day> heuresce <part-of-day>", -5.556828061699537),+                                    ("le <time>named-month", -5.151362953591374),+                                    ("apr\232s le <day-of-month>named-month", -6.249975242259483),+                                    ("\224|vers <time-of-day>du|dans le <part-of-day>",+                                     -5.151362953591374),+                                    ("intersectintersect", -5.844510134151319),+                                    ("de <time-of-day> - <time-of-day> (interval)named-day",+                                     -5.333684510385328),+                                    ("de <datetime> - <datetime> (interval)named-day",+                                     -5.844510134151319),+                                    ("named-dayde <time-of-day> - <time-of-day> (interval)",+                                     -5.844510134151319),+                                    ("dayweek", -4.052750664923264),+                                    ("weekyear", -4.863680881139593),+                                    ("<hour-of-day> <integer> (as relative minutes)named-day",+                                     -5.844510134151319),+                                    ("hh(:|h)mm (time-of-day)intersect", -5.844510134151319),+                                    ("named-monthintersect", -5.844510134151319),+                                    ("dd/-mm\224|vers <time-of-day>", -5.333684510385328),+                                    ("day of month (premier)named-month", -4.5452271500210575),+                                    ("named-day\224|vers <time-of-day>", -4.863680881139593),+                                    ("<day-of-month> <named-month>intersect", -5.844510134151319),+                                    ("intersect\224|vers <time-of-day>", -4.997212273764115),+                                    ("le <time>year", -4.745897845483209),+                                    ("le <time><dim time> <part-of-day>", -5.844510134151319),+                                    ("<time-of-day> - <time-of-day> (interval)named-day",+                                     -4.997212273764115),+                                    ("apr\232s-demain<time-of-day> heures", -5.844510134151319),+                                    ("<datetime> - <datetime> (interval)named-day",+                                     -5.333684510385328)],+                               n = 438},+                   koData =+                     ClassData{prior = -1.3761075158128977, unseen = -6.124683390894205,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -5.429345628954441),+                                    ("hh(:|h)mm (time-of-day)named-day", -5.429345628954441),+                                    ("year<time-of-day> - <time-of-day> (interval)",+                                     -4.736198448394496),+                                    ("demain<time-of-day> heures", -4.736198448394496),+                                    ("hourday", -3.2321210516182215),+                                    ("<day-of-month> <named-month>year", -5.429345628954441),+                                    ("demainavant <time-of-day>", -5.429345628954441),+                                    ("dayhour", -2.4336133554004498),+                                    ("le lendemain du <time>named-month", -5.429345628954441),+                                    ("daymonth", -3.8199077165203406),+                                    ("monthday", -5.429345628954441),+                                    ("monthyear", -4.736198448394496),+                                    ("yearhour", -4.736198448394496),+                                    ("houryear", -5.0238805208462765),+                                    ("aujourd'hui<time-of-day> heures", -5.429345628954441),+                                    ("named-month\224|vers <time-of-day>", -3.724597536716016),+                                    ("<time-of-day> heuresdu|dans le <part-of-day>",+                                     -4.736198448394496),+                                    ("<day-of-week> <day-of-month>named-month", -4.04305126783455),+                                    ("le <time>du|dans le <part-of-day>", -5.0238805208462765),+                                    ("le <day-of-month> (non ordinal)<hour-of-day> <integer> (as relative minutes)",+                                     -4.736198448394496),+                                    ("named-month<day-of-month> <named-month>", -5.429345628954441),+                                    ("<time-of-day> heuresle <day-of-month> (non ordinal)",+                                     -5.0238805208462765),+                                    ("le <day-of-month> (non ordinal)<time-of-day> heures",+                                     -5.429345628954441),+                                    ("aujourd'huidu|dans le <part-of-day>", -5.0238805208462765),+                                    ("le <day-of-month> (non ordinal)named-month",+                                     -5.429345628954441),+                                    ("monthhour", -3.2321210516182215),+                                    ("hourmonth", -4.176582660459073),+                                    ("dayday", -3.6375861597263857),+                                    ("named-dayapr\232s <time-of-day>", -5.0238805208462765),+                                    ("hourhour", -3.8199077165203406),+                                    ("named-day<hour-of-day> <integer> (as relative minutes)",+                                     -5.0238805208462765),+                                    ("dayyear", -4.176582660459073),+                                    ("le <cycle> de <time>named-month", -5.0238805208462765),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -4.736198448394496),+                                    ("demain\224|vers <time-of-day>", -4.513054897080286),+                                    ("<dim time> <part-of-day><hour-of-day> <integer> (as relative minutes)",+                                     -5.0238805208462765),+                                    ("hourminute", -5.0238805208462765),+                                    ("minutemonth", -4.736198448394496),+                                    ("named-monthyear", -4.736198448394496),+                                    ("intersect by 'de' or ','year", -5.0238805208462765),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -3.724597536716016),+                                    ("named-day<datetime> - <datetime> (interval)",+                                     -5.0238805208462765),+                                    ("named-day<day-of-month> <named-month>", -4.04305126783455),+                                    ("weekmonth", -5.0238805208462765),+                                    ("named-dayle <time>", -5.0238805208462765),+                                    ("avant <time-of-day>named-day", -5.429345628954441),+                                    ("de <datetime> - <datetime> (interval)named-month",+                                     -5.429345628954441),+                                    ("le <day-of-month> (non ordinal)year", -5.0238805208462765),+                                    ("named-day<time-of-day> heures", -5.429345628954441),+                                    ("<time-of-day> heuresnamed-day", -3.925268232178167),+                                    ("apr\232s <time-of-day><time-of-day> heures",+                                     -5.0238805208462765),+                                    ("<time-of-day> heuresdd/-mm", -5.429345628954441),+                                    ("<time-of-day> - <time-of-day> (interval)du|dans le <part-of-day>",+                                     -5.0238805208462765),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -5.0238805208462765),+                                    ("le <day-of-month> (non ordinal)\224|vers <time-of-day>",+                                     -4.736198448394496),+                                    ("dayminute", -4.330733340286331),+                                    ("named-monthdu|dans le <part-of-day>", -5.0238805208462765),+                                    ("intersectyear", -5.0238805208462765),+                                    ("minuteday", -4.736198448394496),+                                    ("aujourd'hui\224|vers <time-of-day>", -4.736198448394496),+                                    ("<datetime>-dd <month>(interval)year", -5.0238805208462765),+                                    ("<time-of-day> - <time-of-day> (interval)named-month",+                                     -4.513054897080286),+                                    ("le <day-of-month> (non ordinal)avant <time-of-day>",+                                     -5.429345628954441),+                                    ("<dim time> <part-of-day>apr\232s <time-of-day>",+                                     -5.429345628954441),+                                    ("named-month<time-of-day> heures", -4.330733340286331),+                                    ("demainapr\232s <time-of-day>", -5.429345628954441),+                                    ("<hour-of-day> <integer> (as relative minutes)named-day",+                                     -5.0238805208462765),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -4.513054897080286),+                                    ("<time-of-day> - <time-of-day> (interval)intersect",+                                     -5.429345628954441),+                                    ("apr\232s <time-of-day>\224|vers <time-of-day>",+                                     -4.513054897080286),+                                    ("\224|vers <time-of-day>named-day", -4.736198448394496),+                                    ("le <time>year", -5.0238805208462765),+                                    ("apr\232s <time-of-day>le <day-of-month> (non ordinal)",+                                     -5.429345628954441),+                                    ("de <datetime> - <datetime> (interval)<day-of-month> <named-month>",+                                     -5.429345628954441),+                                    ("minuteyear", -4.04305126783455),+                                    ("yearminute", -4.736198448394496),+                                    ("<dim time> <part-of-day><time-of-day> heures",+                                     -5.429345628954441)],+                               n = 148}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ce <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le <cycle> de <time>",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthmonth", -1.9459101490553135),+                                    ("mois (grain)named-month", -1.9459101490553135),+                                    ("weekday", -1.540445040947149),+                                    ("semaine (grain)<day-of-month> <named-month>",+                                     -1.540445040947149)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("semaine (grain)year (latent)", -1.6739764335716716),+                                    ("weekhour", -1.6739764335716716),+                                    ("semaine (grain)time-of-day (latent)", -1.6739764335716716),+                                    ("weekyear", -1.6739764335716716)],+                               n = 4}}),+       ("<hour-of-day> et trois quarts",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("<time-of-day> heures", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le <day-of-month> \224 <datetime>",+        Classifier{okData =+                     ClassData{prior = -0.325422400434628, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)<time-of-day> heures", -1.9459101490553135),+                                    ("integer (numeric)<dim time> du soir", -2.8622008809294686),+                                    ("integer (numeric)intersect", -2.456735772821304),+                                    ("integer (numeric)<dim time> du matin", -2.8622008809294686),+                                    ("hour", -0.916290731874155),+                                    ("integer (numeric)time-of-day (latent)", -2.169053700369523),+                                    ("integer (numeric)<dim time> <part-of-day>",+                                     -2.456735772821304)],+                               n = 13},+                   koData =+                     ClassData{prior = -1.2809338454620642, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)year (latent)", -1.3350010667323402),+                                    ("year", -1.3350010667323402), ("hour", -2.2512917986064953),+                                    ("integer (numeric)time-of-day (latent)", -2.2512917986064953)],+                               n = 5}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le <cycle> dernier",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("ann\233e (grain)", -1.9459101490553135),+                                    ("semaine (grain)", -1.540445040947149),+                                    ("mois (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135), ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 19}}),+       ("soir de no\235l",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("fin de journ\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("du <datetime>-<day-of-week> dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersectnamed-daynamed-month", -1.9459101490553135),+                                    ("day of month (premier)named-daynamed-month",+                                     -1.9459101490553135),+                                    ("<day-of-week> <day-of-month>named-daynamed-month",+                                     -1.9459101490553135),+                                    ("daydaymonth", -1.252762968495368)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)named-daynamed-month", -1.791759469228055),+                                    ("hourdaymonth", -1.791759469228055),+                                    ("time-of-day (latent)named-daynamed-month",+                                     -1.791759469228055),+                                    ("yeardaymonth", -1.791759469228055)],+                               n = 2}}),+       ("milieu de semaine",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noel",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("fin de matin\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.4228568508200336, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)", -2.5317807984289897e-2)],+                               n = 38},+                   koData =+                     ClassData{prior = -1.0647107369924282,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2578291093020998),+                                    ("numbers 22..29 32..39 .. 52..59", -1.4816045409242156)],+                               n = 20}}),+       ("du dd-<day-of-week> dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -0.6931471805599453),+                                    ("daymonth", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("en semaine",+        Classifier{okData =+                     ClassData{prior = -1.1856236656577395,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -0.3646431135879093, unseen = -3.295836866004329,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 25}}),+       ("numbers 22..29 32..39 .. 52..59",+        Classifier{okData =+                     ClassData{prior = -2.3025850929940455,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (20..60)number (0..16)", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)integer (numeric)", -0.2876820724517809),+                                    ("integer (numeric)number (0..16)", -1.791759469228055)],+                               n = 9}}),+       ("<day-of-week> prochain",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by 'de' or ','",+        Classifier{okData =+                     ClassData{prior = -0.2719337154836418, unseen = -4.394449154672439,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -3.283414346005772),+                                    ("hourmonth", -3.6888794541139363),+                                    ("dayday", -1.742969305058623),+                                    ("named-dayle <cycle> prochain|suivant|d'apr\232s",+                                     -2.3025850929940455),+                                    ("named-day<time-of-day> - <time-of-day> (interval)",+                                     -3.283414346005772),+                                    ("named-dayle <time>", -1.491654876777717),+                                    ("named-dayle <cycle> dernier", -3.6888794541139363),+                                    ("named-day<named-month|named-day> suivant|d'apr\232s",+                                     -2.772588722239781),+                                    ("week-endnamed-month", -3.6888794541139363),+                                    ("dayweek", -1.5488132906176655)],+                               n = 32},+                   koData =+                     ClassData{prior = -1.4350845252893227,+                               unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -2.890371757896165),+                                    ("dayhour", -2.890371757896165),+                                    ("daymonth", -1.9740810260220096),+                                    ("du|dans le <part-of-day>noel", -2.890371757896165),+                                    ("en semainenamed-month", -2.4849066497880004),+                                    ("hourmonth", -2.4849066497880004),+                                    ("dayday", -2.4849066497880004),+                                    ("en semaineintersect", -2.4849066497880004),+                                    ("named-dayle <time>", -2.4849066497880004),+                                    ("named-day<time-of-day> heures", -2.890371757896165),+                                    ("week-endnamed-month", -2.4849066497880004)],+                               n = 10}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.499809670330265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 88},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ce <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("soir", -1.6094379124341003),+                                    ("apr\232s-midi", -1.0986122886681098),+                                    ("hour", -0.7621400520468967)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh(:|h)mm (time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.258096538021482,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 24},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (20..60)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hier",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2876820724517809),+                                    ("numbers 22..29 32..39 .. 52..59", -2.0794415416798357),+                                    ("number (0..16)", -2.0794415416798357)],+                               n = 13}}),+       ("dd-dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime>-<day-of-week> dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersectnamed-daynamed-month", -2.0794415416798357),+                                    ("day of month (premier)named-daynamed-month",+                                     -1.791759469228055),+                                    ("<day-of-week> <day-of-month>named-daynamed-month",+                                     -1.791759469228055),+                                    ("daydaymonth", -0.9808292530117262)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)named-daynamed-month", -1.5686159179138452),+                                    ("hourdaymonth", -1.5686159179138452),+                                    ("time-of-day (latent)named-daynamed-month",+                                     -1.5686159179138452),+                                    ("yeardaymonth", -1.5686159179138452)],+                               n = 8}}),+       ("<dim time> du soir",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>", -1.55814461804655),+                                    ("hour", -0.7472144018302211),+                                    ("<time-of-day> heures", -1.1526795099383855)],+                               n = 8},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8472978603872037),+                                    ("<time-of-day> heures", -0.8472978603872037)],+                               n = 2}}),+       ("aujourd'hui",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("midi",+        Classifier{okData =+                     ClassData{prior = -0.7375989431307791,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -0.6505875661411494, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("toussaint",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("d\233but de soir\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-week> <day-of-month>",+        Classifier{okData =+                     ClassData{prior = -0.24512245803298496,+                               unseen = -3.6888794541139363,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynumber (0..16)", -2.5649493574615367),+                                    ("named-dayinteger (numeric)", -0.8303483020734304),+                                    ("day", -0.719122666963206)],+                               n = 18},+                   koData =+                     ClassData{prior = -1.5260563034950494, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayinteger (numeric)", -0.7731898882334817),+                                    ("day", -0.7731898882334817)],+                               n = 5}}),+       ("d'ici <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.252762968495368), ("day", -1.252762968495368),+                                    ("<integer> <unit-of-duration>", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("\224|vers <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.21936282847430377,+                               unseen = -5.420534999272286,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> timezone", -4.722953221644475),+                                    ("<hour-of-day> et|pass\233 de <number>", -4.31748811353631),+                                    ("hh(:|h)mm (time-of-day)", -4.722953221644475),+                                    ("midi", -4.31748811353631),+                                    ("time-of-day (latent)", -1.587459005715325),+                                    ("<hour-of-day> et|pass\233 de <number> minutes",+                                     -4.31748811353631),+                                    ("minuit", -4.722953221644475),+                                    ("<hour-of-day> et quart", -4.31748811353631),+                                    ("hour", -0.8622235106038793),+                                    ("<hour-of-day> et demi", -4.722953221644475),+                                    ("minute", -2.8511510447428834),+                                    ("<time-of-day> heures", -1.587459005715325),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.8066624897703196)],+                               n = 106},+                   koData =+                     ClassData{prior = -1.6247053845648889, unseen = -4.189654742026425,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)", -3.0757749812275272),+                                    ("time-of-day (latent)", -1.5353299402803784),+                                    ("hour", -1.0388930539664873), ("minute", -2.5649493574615367),+                                    ("<time-of-day> heures", -1.8718021769015913),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.0757749812275272)],+                               n = 26}}),+       ("d\233but <named-month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("d\233but de matin\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("apr\232s-midi",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le <ordinal> <cycle> de <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7047480922384253),+                                    ("ordinals (premier..seizieme)semaine (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinal (digits)jour (grain)named-month",+                                     -1.7047480922384253),+                                    ("weekmonth", -1.2992829841302609),+                                    ("ordinals (premier..seizieme)semaine (grain)intersect",+                                     -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (premier..seizieme)",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("deuxi\232me quinzaine de <named-month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.13858616328614667,+                               unseen = -5.181783550292085,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.9980959022258835),+                                    ("<time-of-day> heuresdu|dans le <part-of-day>",+                                     -2.9789251552376097),+                                    ("le <time>du|dans le <part-of-day>", -3.5667118201397288),+                                    ("\224|vers <time-of-day>ce <part-of-day>",+                                     -3.7898553714539385),+                                    ("named-daymatin", -4.07753744390572),+                                    ("demainsoir", -4.483002552013883),+                                    ("<hour-of-day> et demice <part-of-day>", -3.7898553714539385),+                                    ("hourhour", -1.4872702784598928),+                                    ("aujourd'huiau d\233jeuner", -4.483002552013883),+                                    ("<hour-of-day> et quartce <part-of-day>", -3.7898553714539385),+                                    ("demainapr\232s-midi", -4.483002552013883),+                                    ("minutehour", -2.6112003751122925),+                                    ("named-daydu|dans le <part-of-day>", -3.7898553714539385),+                                    ("intersectdu|dans le <part-of-day>", -2.1316272948504063),+                                    ("le <day-of-month> \224 <datetime>du|dans le <part-of-day>",+                                     -4.07753744390572),+                                    ("named-dayfin d'apr\232s-midi", -4.483002552013883),+                                    ("<day-of-month> <named-month>du|dans le <part-of-day>",+                                     -4.07753744390572),+                                    ("hierdu|dans le <part-of-day>", -4.483002552013883),+                                    ("named-daysoir", -4.483002552013883),+                                    ("aujourd'huid\233but de matin\233e", -3.5667118201397288),+                                    ("<time-of-day> heuresce <part-of-day>", -3.7898553714539385),+                                    ("\224|vers <time-of-day>du|dans le <part-of-day>",+                                     -3.3843902633457743),+                                    ("named-dayapr\232s-midi", -4.483002552013883),+                                    ("intersectapr\232s-midi", -3.5667118201397288),+                                    ("hiersoir", -4.483002552013883)],+                               n = 74},+                   koData =+                     ClassData{prior = -2.044755983691946, unseen = -3.951243718581427,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -2.833213344056216),+                                    ("<time-of-day> heuresdu|dans le <part-of-day>",+                                     -2.5455312716044354),+                                    ("le <time>du|dans le <part-of-day>", -2.833213344056216),+                                    ("aujourd'huidu|dans le <part-of-day>", -2.833213344056216),+                                    ("monthhour", -2.833213344056216),+                                    ("hourhour", -1.8523840910444898),+                                    ("<time-of-day> - <time-of-day> (interval)du|dans le <part-of-day>",+                                     -2.833213344056216),+                                    ("named-monthdu|dans le <part-of-day>", -2.833213344056216)],+                               n = 11}}),+       ("jour de l'an",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.5690945318899665, unseen = -4.553876891600541,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.16126814759612226),+                                    ("number (0..16)", -2.0583881324820035)],+                               n = 90},+                   koData =+                     ClassData{prior = -0.8347976976229721, unseen = -4.304065093204169,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.24740817331384096),+                                    ("numbers 22..29 32..39 .. 52..59", -2.681021528714291),+                                    ("number (20..60)", -3.597312260588446),+                                    ("number (0..16)", -2.093234863812172)],+                               n = 69}}),+       ("apr\232s-demain",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.46262352194811296,+                               unseen = -2.9444389791664407,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 17},+                   koData =+                     ClassData{prior = -0.9932517730102834,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 10}}),+       ("<hour-of-day> et|pass\233 de <number> minutes",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>number (20..60)", -2.3025850929940455),+                                    ("<time-of-day> heuresinteger (numeric)", -2.3025850929940455),+                                    ("\224|vers <time-of-day>number (0..16)", -2.3025850929940455),+                                    ("hour", -0.916290731874155),+                                    ("<time-of-day> heuresnumber (20..60)", -1.8971199848858813),+                                    ("<time-of-day> heuresnumber (0..16)", -1.8971199848858813)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -4.204692619390966,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.580216829592325),+                                    ("number (0..16)semaine (grain)", -3.0910424533583156),+                                    ("number (0..16)ann\233e (grain)", -3.0910424533583156),+                                    ("number (0..16)seconde (grain)", -3.4965075614664802),+                                    ("number (0..16)jour (grain)", -3.4965075614664802),+                                    ("second", -3.4965075614664802),+                                    ("integer (numeric)ann\233e (grain)", -3.4965075614664802),+                                    ("number (0..16)minute (grain)", -3.0910424533583156),+                                    ("integer (numeric)jour (grain)", -3.0910424533583156),+                                    ("day", -2.803360380906535), ("year", -2.803360380906535),+                                    ("number (0..16)mois (grain)", -3.0910424533583156),+                                    ("hour", -2.580216829592325),+                                    ("number (0..16)heure (grain)", -3.0910424533583156),+                                    ("month", -3.0910424533583156),+                                    ("integer (numeric)minute (grain)", -2.803360380906535),+                                    ("minute", -2.3978952727983707),+                                    ("integer (numeric)semaine (grain)", -3.0910424533583156),+                                    ("numbers 22..29 32..39 .. 52..59heure (grain)",+                                     -3.4965075614664802),+                                    ("integer (numeric)heure (grain)", -3.4965075614664802)],+                               n = 22},+                   koData =+                     ClassData{prior = -0.5108256237659907, unseen = -4.48863636973214,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.784189633918261),+                                    ("number (20..60)minute (grain)", -3.784189633918261),+                                    ("number (0..16)jour (grain)", -3.0910424533583156),+                                    ("integer (numeric)ann\233e (grain)", -3.784189633918261),+                                    ("number (0..16)minute (grain)", -3.784189633918261),+                                    ("day", -3.0910424533583156), ("year", -3.784189633918261),+                                    ("hour", -1.2584609896100056),+                                    ("number (0..16)heure (grain)", -1.9123874570166697),+                                    ("month", -3.784189633918261),+                                    ("integer (numeric)minute (grain)", -3.784189633918261),+                                    ("integer (numeric)mois (grain)", -3.784189633918261),+                                    ("minute", -3.0910424533583156),+                                    ("integer (numeric)semaine (grain)", -3.784189633918261),+                                    ("integer (numeric)heure (grain)", -1.9123874570166697)],+                               n = 33}}),+       ("avant-hier",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("d\233but de journ\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("entre <time-of-day> et <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourhour", -2.6741486494265287),+                                    ("miditime-of-day (latent)", -2.6741486494265287),+                                    ("minutehour", -0.9694005571881036),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -2.268683541318364),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -1.9810014688665833),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -1.9810014688665833),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -2.268683541318364)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.8718021769015913,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("minutehour", -1.2992829841302609),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -1.7047480922384253),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -1.7047480922384253)],+                               n = 2}}),+       ("matin",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("en <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("maintenant",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-week> 1er-<day-of-week> dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-daynamed-month", -0.6931471805599453),+                                    ("daydaymonth", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.543294782270004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 92},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("au d\233jeuner",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le lendemain du <time>",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.3862943611198906),+                                    ("<day-of-month> <named-month>", -1.3862943611198906)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)", -1.6094379124341003),+                                    ("time-of-day (latent)", -1.6094379124341003),+                                    ("year", -1.6094379124341003), ("hour", -1.6094379124341003)],+                               n = 2}}),+       ("le <cycle> prochain|suivant|d'apr\232s",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.970291913552122,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.0608719606852628),+                                    ("ann\233e (grain)", -3.258096538021482),+                                    ("semaine (grain)", -1.0608719606852628),+                                    ("mois (grain)", -2.8526314299133175),+                                    ("day", -2.8526314299133175), ("year", -3.258096538021482),+                                    ("jour (grain)", -2.8526314299133175),+                                    ("month", -2.8526314299133175)],+                               n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("apr\232s <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.9267620317414506,+                               unseen = -3.9318256327243257,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.8325814637483102),+                                    ("hh(:|h)mm (time-of-day)", -2.8134107167600364),+                                    ("midi", -3.2188758248682006), ("day", -2.5257286443082556),+                                    ("time-of-day (latent)", -2.8134107167600364),+                                    ("hour", -1.6094379124341003), ("minute", -1.8325814637483102),+                                    ("<time-of-day> heures", -2.8134107167600364),+                                    ("le <time>", -2.8134107167600364),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -2.5257286443082556)],+                               n = 19},+                   koData =+                     ClassData{prior = -0.503905180921417, unseen = -4.2626798770413155,+                               likelihoods =+                                 HashMap.fromList+                                   [("demain", -2.8622008809294686),+                                    ("intersect", -2.169053700369523),+                                    ("le <day-of-month> (non ordinal)", -3.5553480614894135),+                                    ("midi", -1.6835458845878222), ("day", -2.639057329615259),+                                    ("time-of-day (latent)", -2.8622008809294686),+                                    ("hour", -0.9903987040278769),+                                    ("<time-of-day> heures", -2.8622008809294686)],+                               n = 29}}),+       ("dd/-mm",+        Classifier{okData =+                     ClassData{prior = -0.7375989431307791,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -0.6505875661411494, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("minuit",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("entre dd et dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("une <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -2.0281482472922856,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.4849066497880004),+                                    ("ann\233e (grain)", -2.4849066497880004),+                                    ("seconde (grain)", -2.4849066497880004),+                                    ("semaine (grain)", -2.4849066497880004),+                                    ("second", -2.4849066497880004),+                                    ("minute (grain)", -2.4849066497880004),+                                    ("year", -2.4849066497880004),+                                    ("heure (grain)", -2.4849066497880004),+                                    ("hour", -2.4849066497880004), ("minute", -2.4849066497880004)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.14107859825990549,+                               unseen = -4.394449154672439,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.246532418744732),+                                    ("semaine (grain)", -1.246532418744732),+                                    ("mois (grain)", -2.772588722239781),+                                    ("day", -2.3025850929940455),+                                    ("jour (grain)", -2.3025850929940455),+                                    ("month", -2.772588722239781)],+                               n = 33}}),+       ("<hour-of-day> et quart",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("midi", -2.1972245773362196),+                                    ("\224|vers <time-of-day>", -1.791759469228055),+                                    ("hour", -0.8109302162163288),+                                    ("<time-of-day> heures", -1.2809338454620642)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (0..16)",+        Classifier{okData =+                     ClassData{prior = -0.2076393647782445, unseen = -3.713572066704308,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 39},+                   koData =+                     ClassData{prior = -1.6739764335716716,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9}}),+       ("heure (grain)",+        Classifier{okData =+                     ClassData{prior = -1.540445040947149, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -0.2411620568168881,+                               unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22}}),+       ("<named-month|named-day> dernier|pass\233",+        Classifier{okData =+                     ClassData{prior = -2.3978952727983707,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.791759469228055), ("named-day", -1.791759469228055)],+                               n = 1},+                   koData =+                     ClassData{prior = -9.53101798043249e-2,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)", -2.70805020110221),+                                    ("en semaine", -2.3025850929940455),+                                    ("day", -1.791759469228055),+                                    ("\224|vers <time-of-day>", -2.70805020110221),+                                    ("time-of-day (latent)", -2.70805020110221),+                                    ("year", -2.70805020110221), ("hour", -1.6094379124341003),+                                    ("<time-of-day> heures", -2.0149030205422647),+                                    ("le <time>", -2.3025850929940455)],+                               n = 10}}),+       ("dd/-mm/-yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("fin de semaine",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd mm yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day of month (premier)",+        Classifier{okData =+                     ClassData{prior = -6.899287148695143e-2,+                               unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -2.70805020110221, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("jour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.1466034741918754, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -1.9924301646902063,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("dd mm",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("dernier <cycle> de <time> (latent)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.4816045409242156),+                                    ("semaine (grain)intersect", -1.9924301646902063),+                                    ("weekmonth", -1.4816045409242156),+                                    ("semaine (grain)named-month", -1.9924301646902063),+                                    ("jour (grain)intersect", -1.9924301646902063),+                                    ("jour (grain)named-month", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("avant le d\233jeuner",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("1er mai",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("fin de soir\233e",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.0185695809945732, unseen = -4.454347296253507,+                               likelihoods =+                                 HashMap.fromList+                                   [("demain<time-of-day> heures", -3.7495040759303713),+                                    ("day of month (premier)<day-of-week> <day-of-month>",+                                     -3.056356895370426),+                                    ("dayhour", -3.3440389678222067),+                                    ("hh(:|h)mm (time-of-day)<hour-of-day> <integer> (as relative minutes)",+                                     -3.3440389678222067),+                                    ("le <day-of-month> (non ordinal)<time-of-day> heures",+                                     -3.7495040759303713),+                                    ("minuteminute", -2.044755983691946),+                                    ("<day-of-month> <named-month><day-of-month> <named-month>",+                                     -3.3440389678222067),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -3.056356895370426),+                                    ("dayday", -1.8777018990287797),+                                    ("<day-of-week> <day-of-month><day-of-week> <day-of-month>",+                                     -3.7495040759303713),+                                    ("<day-of-month> <named-month>day of month (premier)",+                                     -3.3440389678222067),+                                    ("minutehour", -3.3440389678222067),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -3.7495040759303713),+                                    ("<hour-of-day> <integer> (as relative minutes)hh(:|h)mm (time-of-day)",+                                     -3.056356895370426),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.7495040759303713),+                                    ("<hour-of-day> <integer> (as relative minutes)<hour-of-day> <integer> (as relative minutes)",+                                     -3.3440389678222067),+                                    ("<day-of-month> <named-month>intersect", -3.3440389678222067),+                                    ("intersect<day-of-week> <day-of-month>", -3.3440389678222067)],+                               n = 26},+                   koData =+                     ClassData{prior = -0.4480247225269604, unseen = -4.836281906951478,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -3.7297014486341915),+                                    ("monthday", -2.8824035882469876),+                                    ("intersectnamed-day", -3.7297014486341915),+                                    ("day of month (premier)named-day", -3.4420193761824103),+                                    ("named-month<day-of-month> <named-month>",+                                     -3.7297014486341915),+                                    ("minuteminute", -3.7297014486341915),+                                    ("dayday", -1.4961092271270973),+                                    ("<day-of-week> <day-of-month><day-of-week> <day-of-month>",+                                     -3.7297014486341915),+                                    ("day of month (premier)<day-of-month> <named-month>",+                                     -4.135166556742356),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -3.4420193761824103),+                                    ("minutehour", -2.631089159966082),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -3.4420193761824103),+                                    ("day of month (premier)intersect", -2.8824035882469876),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.4420193761824103),+                                    ("intersectintersect", -3.2188758248682006),+                                    ("hh(:|h)mm (time-of-day)intersect", -3.7297014486341915),+                                    ("named-monthintersect", -3.7297014486341915),+                                    ("<day-of-week> <day-of-month>named-day", -3.4420193761824103),+                                    ("named-monthday of month (premier)", -3.7297014486341915),+                                    ("<day-of-week> <day-of-month>intersect", -2.8824035882469876),+                                    ("yearminute", -3.4420193761824103)],+                               n = 46}}),+       ("<day-of-month> <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.30010459245033816,+                               unseen = -4.418840607796598,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 40},+                   koData =+                     ClassData{prior = -1.349926716949016, unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 14}}),+       ("<cycle> prochain|suivant|d'apr\232s",+        Classifier{okData =+                     ClassData{prior = -8.338160893905101e-2,+                               unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.0986122886681098),+                                    ("ann\233e (grain)", -3.295836866004329),+                                    ("semaine (grain)", -1.0986122886681098),+                                    ("mois (grain)", -2.890371757896165),+                                    ("day", -2.6026896854443837), ("year", -3.295836866004329),+                                    ("jour (grain)", -2.6026896854443837),+                                    ("month", -2.890371757896165)],+                               n = 23},+                   koData =+                     ClassData{prior = -2.5257286443082556,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("mois (grain)", -1.791759469228055),+                                    ("day", -1.791759469228055),+                                    ("jour (grain)", -1.791759469228055),+                                    ("month", -1.791759469228055)],+                               n = 2}}),+       ("fin <named-month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.2321436812926323, unseen = -4.0943445622221,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)<hour-of-day> <integer> (as relative minutes)",+                                     -2.691243082785829),+                                    ("minuteminute", -1.3694872428035094),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -3.3843902633457743),+                                    ("<time-of-day> heures<time-of-day> heures",+                                     -3.3843902633457743),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -2.468099531471619),+                                    ("hourhour", -2.691243082785829),+                                    ("minutehour", -2.468099531471619),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -2.691243082785829),+                                    ("<hour-of-day> <integer> (as relative minutes)hh(:|h)mm (time-of-day)",+                                     -2.468099531471619),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.3843902633457743),+                                    ("<hour-of-day> <integer> (as relative minutes)<hour-of-day> <integer> (as relative minutes)",+                                     -2.691243082785829),+                                    ("<time-of-day> heurestime-of-day (latent)",+                                     -3.3843902633457743)],+                               n = 21},+                   koData =+                     ClassData{prior = -0.3448404862917295, unseen = -4.787491742782046,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)time-of-day (latent)",+                                     -1.7833912195575383),+                                    ("hourhour", -1.3451362886263831),+                                    ("time-of-day (latent)<hour-of-day> <integer> (as relative minutes)",+                                     -4.085976312551584),+                                    ("hourminute", -4.085976312551584),+                                    ("minutehour", -1.7346010553881064),+                                    ("hh(:|h)mm (time-of-day)time-of-day (latent)",+                                     -2.987364023883474),+                                    ("<hour-of-day> <integer> (as relative minutes)<time-of-day> heures",+                                     -3.169685580677429),+                                    ("hh(:|h)mm (time-of-day)<time-of-day> heures",+                                     -3.169685580677429),+                                    ("<hour-of-day> <integer> (as relative minutes)time-of-day (latent)",+                                     -2.6996819514316934),+                                    ("time-of-day (latent)<time-of-day> heures",+                                     -2.2942168433235293)],+                               n = 51}}),+       ("<named-day> en huit",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> et demi",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("midi", -1.791759469228055),+                                    ("\224|vers <time-of-day>", -1.791759469228055),+                                    ("hour", -0.8754687373538999),+                                    ("<time-of-day> heures", -1.3862943611198906)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dernier week-end de <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("du dd au dd(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -1.8718021769015913,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11}}),+       ("avant <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.3862943611198906, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.7346010553881064),+                                    ("hour", -1.2237754316221157),+                                    ("<time-of-day> heures", -1.7346010553881064)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.803360380906535),+                                    ("hh(:|h)mm (time-of-day)", -2.803360380906535),+                                    ("hier", -2.803360380906535), ("day", -2.803360380906535),+                                    ("time-of-day (latent)", -1.8870696490323797),+                                    ("hour", -1.1939224684724346), ("minute", -2.3978952727983707),+                                    ("<time-of-day> heures", -1.8870696490323797),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -2.803360380906535)],+                               n = 12}}),+       ("fin d'apr\232s-midi",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<part-of-day> du <dim time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("matin<day-of-month> <named-month>", -1.0986122886681098),+                                    ("hourday", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("matinyear (latent)", -1.0986122886681098),+                                    ("houryear", -1.0986122886681098)],+                               n = 1}}),+       ("<time-of-day> heures",+        Classifier{okData =+                     ClassData{prior = -0.16251892949777494,+                               unseen = -5.634789603169249,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>", -1.8025703853322705),+                                    ("time-of-day (latent)", -1.1538749673431592),+                                    ("apr\232s <time-of-day>", -4.532599493153256),+                                    ("hour", -0.7112308559932407),+                                    ("avant <time-of-day>", -4.532599493153256)],+                               n = 136},+                   koData =+                     ClassData{prior = -1.8971199848858813, unseen = -4.02535169073515,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>", -1.7047480922384253),+                                    ("time-of-day (latent)", -1.927891643552635),+                                    ("apr\232s <time-of-day>", -2.6210388241125804),+                                    ("hour", -0.8292793548845253),+                                    ("avant <time-of-day>", -2.3978952727983707),+                                    ("minute", -3.3141860046725258),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.3141860046725258)],+                               n = 24}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("le <time>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809, unseen = -5.739792912179234,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.4784757594577096),+                                    ("<named-month|named-day> suivant|d'apr\232s",+                                     -3.5393477201429726),+                                    ("<ordinal> <cycle> de <time>", -4.350277936359301),+                                    ("premi\232re quinzaine de <named-month>(interval)",+                                     -5.043425116919247),+                                    ("intersect", -2.0476928433652555),+                                    ("soir de no\235l", -5.043425116919247),+                                    ("en semaine", -3.3386770246808215),+                                    ("toussaint", -4.637960008811082), ("day", -1.3421231428067533),+                                    ("deuxi\232me quinzaine de <named-month>(interval)",+                                     -5.043425116919247),+                                    ("<dim time> <part-of-day>", -4.127134385045092),+                                    ("dd/-mm", -3.7906621484238787),+                                    ("dd/-mm/-yyyy", -4.350277936359301),+                                    ("dd mm yyyy", -3.7906621484238787),+                                    ("day of month (premier)", -3.9448128282511368),+                                    ("dd mm", -3.7906621484238787), ("hour", -2.2102117728630306),+                                    ("month", -4.350277936359301),+                                    ("dernier <cycle> de <time> (latent)", -4.127134385045092),+                                    ("<day-of-month> <named-month>", -3.028522096376982),+                                    ("<cycle> prochain|suivant|d'apr\232s", -2.6920498597557687),+                                    ("dernier week-end de <time>", -5.043425116919247),+                                    ("<ordinal> week-end de <time>", -4.637960008811082),+                                    ("<cycle> dernier", -3.9448128282511368)],+                               n = 141},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -4.812184355372417,+                               likelihoods =+                                 HashMap.fromList+                                   [("<named-month|named-day> suivant|d'apr\232s",+                                     -4.110873864173311),+                                    ("intersect", -3.1945831322991562),+                                    ("en semaine", -2.23907168727172), ("day", -1.625967214385311),+                                    ("<dim time> <part-of-day>", -3.7054087560651467),+                                    ("dd/-mm", -3.417726683613366),+                                    ("<named-month|named-day> dernier|pass\233",+                                     -3.7054087560651467),+                                    ("day of month (premier)", -4.110873864173311),+                                    ("dd mm", -3.417726683613366), ("hour", -2.0959708436310467),+                                    ("<day-of-month> <named-month>", -4.110873864173311),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -2.406125771934886),+                                    ("minute", -2.406125771934886),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -2.606796467397037)],+                               n = 47}}),+       ("apr\232s le <day-of-month>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("n <cycle> passes|precedents",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("integer (numeric)ann\233e (grain)", -1.6094379124341003),+                                    ("year", -1.6094379124341003),+                                    ("integer (numeric)semaine (grain)", -1.6094379124341003)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.3862943611198906),+                                    ("number (0..16)heure (grain)", -1.3862943611198906)],+                               n = 1}}),+       ("il y a <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8718021769015913), ("year", -1.8718021769015913),+                                    ("<integer> <unit-of-duration>", -0.9555114450274363),+                                    ("hour", -1.8718021769015913), ("month", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> week-end de <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (premier..seizieme)named-month",+                                     -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> du matin",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224|vers <time-of-day>", -1.7346010553881064),+                                    ("hour", -0.7537718023763802),+                                    ("<time-of-day> heures", -1.041453874828161)],+                               n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.916290731874155),+                                    ("<time-of-day> heures", -0.916290731874155)],+                               n = 1}}),+       ("d\233but d'apr\232s-midi",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -0.8174448972375224, unseen = -4.430816798843313,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuitnumber (0..16)", -3.3202283191284883),+                                    ("midinumber (20..60)", -3.7256934272366524),+                                    ("\224|vers <time-of-day>number (20..60)", -3.7256934272366524),+                                    ("<time-of-day> heuresinteger (numeric)", -1.2833463918674481),+                                    ("\224|vers <time-of-day>number (0..16)", -3.3202283191284883),+                                    ("midinumber (0..16)", -3.7256934272366524),+                                    ("hour", -0.8634925463071842),+                                    ("<time-of-day> heuresnumber (20..60)", -3.3202283191284883),+                                    ("\224|vers <time-of-day>integer (numeric)",+                                     -3.7256934272366524),+                                    ("<time-of-day> heuresnumber (0..16)", -3.3202283191284883)],+                               n = 34},+                   koData =+                     ClassData{prior = -0.5826053061601215, unseen = -4.624972813284271,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)numbers 22..29 32..39 .. 52..59",+                                     -3.9219733362813143),+                                    ("time-of-day (latent)number (0..16)", -3.5165082281731497),+                                    ("<time-of-day> heuresinteger (numeric)", -2.6692103677859462),+                                    ("avant <time-of-day>integer (numeric)", -3.9219733362813143),+                                    ("time-of-day (latent)integer (numeric)", -1.2829160066660554),+                                    ("apr\232s <time-of-day>integer (numeric)", -3.228826155721369),+                                    ("hour", -0.8309308829229983),+                                    ("\224|vers <time-of-day>integer (numeric)",+                                     -3.5165082281731497),+                                    ("<time-of-day> heuresnumber (0..16)", -3.9219733362813143)],+                               n = 43}}),+       ("<cycle> dernier",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9924301646902063),+                                    ("ann\233e (grain)", -2.3978952727983707),+                                    ("semaine (grain)", -1.9924301646902063),+                                    ("mois (grain)", -2.3978952727983707),+                                    ("day", -1.9924301646902063), ("year", -2.3978952727983707),+                                    ("jour (grain)", -1.9924301646902063),+                                    ("month", -2.3978952727983707)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("heure (grain)", -1.791759469228055),+                                    ("hour", -1.791759469228055)],+                               n = 1}}),+       ("ce|dans le <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2992829841302609),+                                    ("ann\233e (grain)", -2.3978952727983707),+                                    ("semaine (grain)", -1.2992829841302609),+                                    ("day", -1.9924301646902063), ("year", -2.3978952727983707),+                                    ("jour (grain)", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ce <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("soir", -1.466337068793427), ("day", -1.8718021769015913),+                                    ("named-day", -1.8718021769015913),+                                    ("hour", -1.1786549963416462),+                                    ("week-end", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/GA.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.GA (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("ar\250 am\225rach",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd/mm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("inniu",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("<time> seo chugainn",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.8266785731844679),+                                    ("d\233 named-day", -2.0794415416798357),+                                    ("named-day", -1.3862943611198906),+                                    ("an named-day", -1.6739764335716716)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("d\233 named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("anois",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("an named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("am\225rach",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("inn\233",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<time> seo",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.7985076962177716),+                                    ("d\233 named-day", -2.3025850929940455),+                                    ("named-day", -1.3862943611198906),+                                    ("an named-day", -1.6094379124341003)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ar\250 inn\233",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/HE.hs view
@@ -0,0 +1,992 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.HE (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -1.110882381259924, unseen = -3.367295829986474,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 27},+                   koData =+                     ClassData{prior = -0.3993860620317821, unseen = -4.04305126783455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 55}}),+       ("\1489 <date>",+        Classifier{okData =+                     ClassData{prior = -0.12783337150988489,+                               unseen = -4.1588830833596715,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.044522437723423),+                                    ("<time> <part-of-day>", -3.4499875458315876),+                                    ("mm/dd", -3.4499875458315876),+                                    ("intersect", -3.044522437723423),+                                    ("named-month", -2.5336968139574325),+                                    ("day", -2.1972245773362196),+                                    ("this <cycle>", -3.4499875458315876),+                                    ("time-of-day (latent)", -3.044522437723423),+                                    ("<time-of-day> am|pm", -3.4499875458315876),+                                    ("named-day", -3.044522437723423),+                                    ("current <day-of-week>", -3.4499875458315876),+                                    ("last <time>", -3.4499875458315876),+                                    ("hour", -1.7452394535931621), ("month", -2.5336968139574325),+                                    ("last <cycle>", -3.4499875458315876),+                                    ("<named-month> <day-of-month> (non ordinal)",+                                     -3.4499875458315876),+                                    ("week-end", -3.044522437723423),+                                    ("this <time>", -3.044522437723423)],+                               n = 22},+                   koData =+                     ClassData{prior = -2.120263536200091, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -2.5257286443082556), ("day", -2.120263536200091),+                                    ("<day-of-month> (ordinal)", -2.5257286443082556),+                                    ("month", -2.5257286443082556),+                                    ("this <time>", -2.5257286443082556)],+                               n = 3}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.4213856809311607),+                                    ("\1489 <date>morning", -2.6741486494265287),+                                    ("yesterdayevening|night", -2.6741486494265287),+                                    ("hourhour", -1.9810014688665833),+                                    ("time-of-day (latent)morning", -2.6741486494265287),+                                    ("named-daymorning", -2.6741486494265287),+                                    ("todayevening|night", -2.6741486494265287),+                                    ("tomorrowlunch", -2.268683541318364),+                                    ("at <time-of-day>morning", -2.6741486494265287),+                                    ("tomorrowevening|night", -2.6741486494265287)],+                               n = 9},+                   koData =+                     ClassData{prior = -2.3025850929940455, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.8718021769015913),+                                    ("<day-of-month> (ordinal)morning", -1.8718021769015913)],+                               n = 1}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.0986122886681098),+                                    ("<time-of-day> am|pm", -1.5040773967762742),+                                    ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("<day-of-month> (non ordinal) of <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.8649974374866046),+                                    ("month", -0.7472144018302211),+                                    ("integer 3named-month", -2.2512917986064953)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the ides of <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 4",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("\1489 <named-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 9",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("integer 21..99 (with and)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods =+                                 HashMap.fromList [("integer (20..90)integer 4", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -4.852030263919617,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -2.646962509122372),+                                    ("daymonth", -3.2347491740244907),+                                    ("monthyear", -3.7455747977904816),+                                    ("the <day-of-month> (ordinal)in <named-month>",+                                     -3.7455747977904816),+                                    ("intersect<time-of-day> am|pm", -4.151039905898646),+                                    ("<time> <part-of-day>\1489 <named-day>", -3.457892725338701),+                                    ("intersect by \",\"<time-of-day> am|pm", -3.2347491740244907),+                                    ("last <day-of-week> of <time>year", -4.151039905898646),+                                    ("dayday", -2.7647455447787554),+                                    ("the <day-of-month> (ordinal)\1489 <date>",+                                     -3.7455747977904816),+                                    ("dayyear", -2.359280436670591),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -3.7455747977904816),+                                    ("\1489 <date>\1489 <named-day>", -4.151039905898646),+                                    ("named-monthyear", -3.7455747977904816),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.151039905898646),+                                    ("absorption of , after named day<day-of-month> (ordinal) of <named-month>",+                                     -4.151039905898646),+                                    ("<day-of-month> (ordinal) of <named-month>year",+                                     -3.457892725338701),+                                    ("named-daynext <cycle>", -4.151039905898646),+                                    ("dayminute", -2.7647455447787554),+                                    ("named-day<day-of-month> (ordinal) of <named-month>",+                                     -4.151039905898646),+                                    ("named-day\1489 <date>", -4.151039905898646),+                                    ("absorption of , after named dayintersect",+                                     -4.151039905898646),+                                    ("named-day<day-of-month> (non ordinal) of <named-month>",+                                     -4.151039905898646),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -3.7455747977904816),+                                    ("year<time-of-day> am|pm", -4.151039905898646),+                                    ("\1489 <date>\1489 <date>", -4.151039905898646),+                                    ("<day-of-month> (non ordinal) of <named-month>year",+                                     -3.457892725338701),+                                    ("absorption of , after named day<day-of-month> (non ordinal) of <named-month>",+                                     -4.151039905898646),+                                    ("dayweek", -3.7455747977904816),+                                    ("<time> <part-of-day>\1489 <date>", -3.457892725338701),+                                    ("named-daythe <day-of-month> (ordinal)", -4.151039905898646),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -3.7455747977904816),+                                    ("yearminute", -4.151039905898646)],+                               n = 42},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -4.454347296253507,+                               likelihoods =+                                 HashMap.fromList+                                   [("in <named-month>year", -3.7495040759303713),+                                    ("dayhour", -3.3440389678222067),+                                    ("year<hour-of-day> <integer>", -3.3440389678222067),+                                    ("daymonth", -3.056356895370426),+                                    ("monthyear", -2.6508917872622613),+                                    ("intersecthh:mm", -3.7495040759303713),+                                    ("dayday", -3.7495040759303713),+                                    ("intersect by \",\"hh:mm", -2.833213344056216),+                                    ("named-monthyear", -3.056356895370426),+                                    ("absorption of , after named daynamed-month",+                                     -3.7495040759303713),+                                    ("named-dayin <named-month>", -3.7495040759303713),+                                    ("dayminute", -2.3632097148104805),+                                    ("named-day\1489 <date>", -3.7495040759303713),+                                    ("absorption of , after named dayintersect",+                                     -3.7495040759303713),+                                    ("yearhh:mm", -3.7495040759303713),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -3.7495040759303713),+                                    ("\1489 <date>year", -3.7495040759303713),+                                    ("named-daythe <day-of-month> (ordinal)", -3.7495040759303713),+                                    ("tomorrownoon", -3.3440389678222067),+                                    ("yearminute", -3.056356895370426)],+                               n = 21}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("month (grain)", -1.9459101490553135),+                                    ("year (grain)", -1.9459101490553135),+                                    ("week (grain)", -1.540445040947149),+                                    ("year", -1.9459101490553135), ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening|night",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 3",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal) of <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal 3named-month", -1.9459101490553135),+                                    ("ordinal (digits)named-month", -0.9650808960435872),+                                    ("month", -0.7419373447293773)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> and <integer>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer 4", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer 10", -1.7047480922384253),+                                    ("time-of-day (latent)integer (numeric)", -1.0116009116784799),+                                    ("hour", -0.7884573603642702)],+                               n = 4}}),+       ("ordinal 19",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer 11..19",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer 9integer 10", 0.0)],+                               n = 1}}),+       ("integer 7",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal 3\1489 <date>", -1.7346010553881064),+                                    ("ordinal (digits)in <named-month>", -2.1400661634962708),+                                    ("month", -0.8873031950009028),+                                    ("ordinal 3in <named-month>", -1.7346010553881064),+                                    ("ordinal (digits)\1489 <date>", -2.1400661634962708)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 6}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 2",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal 3", -1.252762968495368),+                                    ("ordinal 19", -1.252762968495368),+                                    ("ordinal (digits)", -1.252762968495368)],+                               n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("ordinal 9", -0.916290731874155)],+                               n = 1}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("week (grain)", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 7",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -1.2809338454620642,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.4700036292457356),+                                    ("integer 9", -1.3862943611198906)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.325422400434628, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2876820724517809),+                                    ("integer (20..90)", -2.0794415416798357),+                                    ("integer 9", -2.0794415416798357)],+                               n = 13}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 8},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("integer 9",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.8109302162163288),+                                    ("named-dayintersect", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer 21..99 (with and)hour (grain)", -2.3025850929940455),+                                    ("day", -1.8971199848858813),+                                    ("integer 7day (grain)", -1.8971199848858813),+                                    ("hour", -1.8971199848858813),+                                    ("integer (numeric)minute (grain)", -1.8971199848858813),+                                    ("minute", -1.8971199848858813),+                                    ("integer (numeric)hour (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.6094379124341003),+                                    ("integer 4hour (grain)", -1.6094379124341003)],+                               n = 1}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.3629054936893685,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("\1489 <date>", -2.9444389791664407),+                                    ("at <time-of-day>", -2.9444389791664407),+                                    ("time-of-day (latent)", -2.2512917986064953),+                                    ("hh:mm", -1.1526795099383855), ("hour", -1.845826690498331),+                                    ("minute", -1.1526795099383855)],+                               n = 16},+                   koData =+                     ClassData{prior = -1.1895840668738362, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 7}}),+       ("integer 10",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.3794896217049037,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect by \",\"year", -3.044522437723423),+                                    ("dayday", -2.128231705849268),+                                    ("named-dayintersect by \",\"", -2.639057329615259),+                                    ("dayyear", -2.128231705849268),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -3.044522437723423),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -3.044522437723423),+                                    ("intersect by \",\"intersect", -3.044522437723423),+                                    ("named-dayintersect", -3.044522437723423),+                                    ("dayminute", -1.9459101490553135),+                                    ("named-day<day-of-month> (ordinal) of <named-month>",+                                     -3.044522437723423),+                                    ("intersectyear", -3.044522437723423),+                                    ("named-day<day-of-month> (non ordinal) of <named-month>",+                                     -3.044522437723423),+                                    ("intersectintersect", -3.044522437723423),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -2.639057329615259)],+                               n = 13},+                   koData =+                     ClassData{prior = -1.1526795099383855, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.639057329615259),+                                    ("daymonth", -2.639057329615259),+                                    ("named-dayintersect by \",\"", -2.639057329615259),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -2.639057329615259),+                                    ("intersect by \",\"intersect", -2.639057329615259),+                                    ("named-dayintersect", -2.639057329615259),+                                    ("dayminute", -1.540445040947149),+                                    ("intersectintersect", -2.639057329615259)],+                               n = 6}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -7.410797215372185e-2,+                               unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -2.639057329615259, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = -3.7740327982847086e-2,+                               unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -3.295836866004329, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("ordinal 1",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("current <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("\1489 <date>", -1.9459101490553135),+                                    ("\1489 <named-day>", -1.9459101490553135),+                                    ("day", -0.8472978603872037),+                                    ("named-day", -1.252762968495368)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer 4",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter of an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-day> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayordinal (digits)", -0.916290731874155),+                                    ("day", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("absorption of , after named dayordinal (digits)",+                                     -0.916290731874155),+                                    ("day", -0.916290731874155)],+                               n = 1}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 6",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("integer 3",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("\1489 <date>", -1.791759469228055),+                                    ("day", -1.791759469228055), ("named-day", -1.791759469228055),+                                    ("hour", -1.3862943611198906),+                                    ("week-end", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.9808292530117262),+                                    ("named-day", -1.6739764335716716),+                                    ("<day-of-month> (ordinal)", -1.3862943611198906)],+                               n = 5}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal 4", -1.7047480922384253),+                                    ("ordinal 3", -1.7047480922384253),+                                    ("ordinal 2", -1.0116009116784799),+                                    ("ordinal 1", -1.2992829841302609)],+                               n = 7}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.0986122886681098),+                                    ("month", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.916290731874155), ("named-day", -0.916290731874155)],+                               n = 3}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.0986122886681098),+                                    ("month (grain)", -1.791759469228055),+                                    ("week (grain)", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 20..90",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("hhmm (military) am|pm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -2.3025850929940455),+                                    ("half an hour", -2.3025850929940455),+                                    ("<integer> <unit-of-duration>", -1.2039728043259361),+                                    ("quarter of an hour", -2.3025850929940455),+                                    ("hour", -1.8971199848858813), ("minute", -1.3862943611198906)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("year<hour-of-day> <integer>", -0.6931471805599453),+                                    ("yearminute", -0.6931471805599453)],+                               n = 2}}),+       ("in <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal 5",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("in <named-month>integer (numeric)", -2.1972245773362196),+                                    ("\1489 <date>integer (numeric)", -2.1972245773362196),+                                    ("named-monthinteger (numeric)", -1.0986122886681098),+                                    ("month", -0.8109302162163288)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)in <named-month>", -1.8718021769015913),+                                    ("integer 3\1489 <date>", -1.8718021769015913),+                                    ("integer (numeric)\1489 <date>", -1.8718021769015913),+                                    ("month", -0.9555114450274363),+                                    ("integer 3in <named-month>", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal 3\1489 <date>", -1.252762968495368),+                                    ("month", -0.8472978603872037),+                                    ("ordinal 3in <named-month>", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("\1489 <date>", -1.9459101490553135),+                                    ("\1489 <named-day>", -2.3513752571634776),+                                    ("day", -1.252762968495368), ("named-day", -1.6582280766035324),+                                    ("hour", -1.9459101490553135),+                                    ("week-end", -2.3513752571634776)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.0116009116784799, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("\1489 <date>", -2.0149030205422647),+                                    ("day", -1.0986122886681098),+                                    ("<day-of-month> (ordinal)", -1.3217558399823195)],+                               n = 4}})]
+ Duckling/Ranking/Classifiers/HR.hs view
@@ -0,0 +1,1850 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.HR (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -1.7047480922384253),+                                    ("intersect", -1.7047480922384253),+                                    ("hh:mm", -1.7047480922384253), ("hour", -1.7047480922384253),+                                    ("minute", -1.2992829841302609)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.9697794168251413, unseen = -4.532599493153256,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 91},+                   koData =+                     ClassData{prior = -0.4766926173965321, unseen = -5.017279836814924,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 149}}),+       ("Father's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("few",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3184537311185346, unseen = -5.19295685089021,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clockmorning", -4.4942386252808095),+                                    ("until <time-of-day>afternoon", -4.4942386252808095),+                                    ("dayhour", -2.7894905330423847),+                                    ("time-of-day (latent)late night", -3.801091444720864),+                                    ("time-of-day (latent)evening|night", -4.088773517172645),+                                    ("<time-of-day> o'clockevening|night", -4.4942386252808095),+                                    ("<time-of-day> o'clocktonight", -4.4942386252808095),+                                    ("<hour-of-day> halfafternoon", -4.4942386252808095),+                                    ("time-of-day (latent)tonight", -4.088773517172645),+                                    ("yesterdayevening|night", -4.4942386252808095),+                                    ("hourhour", -1.4497161875573867),+                                    ("at <time-of-day>afternoon", -3.3956263366127),+                                    ("minutehour", -2.5483284762254965),+                                    ("<time-of-day> o'clockafternoon", -4.4942386252808095),+                                    ("intersectafternoon", -4.4942386252808095),+                                    ("time-of-day (latent)morning", -4.4942386252808095),+                                    ("named-daymorning", -4.4942386252808095),+                                    ("todayevening|night", -4.4942386252808095),+                                    ("named-dayearly morning", -3.801091444720864),+                                    ("at <time-of-day>late night", -3.801091444720864),+                                    ("hh:mmearly morning", -4.4942386252808095),+                                    ("<day-of-month>(ordinal) <named-month>morning",+                                     -4.4942386252808095),+                                    ("half <integer> (HR style hour-of-day)afternoon",+                                     -4.088773517172645),+                                    ("numeral after|past (hour-of-day)afternoon",+                                     -4.4942386252808095),+                                    ("quarter after|past (hour-of-day)afternoon",+                                     -4.4942386252808095),+                                    ("<time-of-day> o'clocklate night", -4.088773517172645),+                                    ("tomorrowlunch", -4.4942386252808095),+                                    ("todaytonight", -4.4942386252808095),+                                    ("time-of-day (latent)afternoon", -3.2414756567854415),+                                    ("intersectmorning", -3.2414756567854415),+                                    ("about <time-of-day>afternoon", -3.801091444720864),+                                    ("hh:mmafternoon", -3.2414756567854415),+                                    ("between <datetime> and <datetime> (interval)morning",+                                     -4.4942386252808095),+                                    ("between <time-of-day> and <time-of-day> (interval)morning",+                                     -4.4942386252808095),+                                    ("at <time-of-day>morning", -4.4942386252808095),+                                    ("tomorrowevening|night", -4.4942386252808095)],+                               n = 64},+                   koData =+                     ClassData{prior = -1.2992829841302609, unseen = -4.605170185988091,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clockmorning", -3.9019726695746444),+                                    ("dayhour", -3.4965075614664802),+                                    ("yearhour", -3.4965075614664802),+                                    ("named-daylate night", -3.9019726695746444),+                                    ("monthhour", -3.4965075614664802),+                                    ("by <time>afternoon", -3.9019726695746444),+                                    ("after <time-of-day>morning", -3.9019726695746444),+                                    ("hourhour", -2.1972245773362196),+                                    ("until <time-of-day>morning", -3.9019726695746444),+                                    ("since <time-of-day>morning", -3.9019726695746444),+                                    ("minutehour", -2.649209701079277),+                                    ("time-of-day (latent)morning", -3.9019726695746444),+                                    ("year (latent)afternoon", -3.4965075614664802),+                                    ("by <time>morning", -3.9019726695746444),+                                    ("numeral to|till|before <integer> (hour-of-day)morning",+                                     -3.9019726695746444),+                                    ("named-monthmorning", -3.9019726695746444),+                                    ("secondhour", -3.4965075614664802),+                                    ("time-of-day (latent)afternoon", -2.515678308454754),+                                    ("intersectmorning", -3.4965075614664802),+                                    ("<duration> after <time>afternoon", -3.9019726695746444),+                                    ("named-monthlate night", -3.9019726695746444),+                                    ("<day-of-month>(ordinal) <named-month>late night",+                                     -3.9019726695746444)],+                               n = 24}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = -1.1526795099383855,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -0.3794896217049037, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clock", -2.2823823856765264),+                                    ("time-of-day (latent)", -1.1192315758708455),+                                    ("hh:mm", -2.505525936990736), ("hour", -0.8960880245566356),+                                    ("minute", -2.505525936990736)],+                               n = 22},+                   koData =+                     ClassData{prior = -1.8718021769015913, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.9555114450274363),+                                    ("hour", -0.9555114450274363)],+                               n = 4}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.7282385003712154),+                                    ("named-day", -0.8823891801984737),+                                    ("u <named-day>", -2.268683541318364)],+                               n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.15822400521489416,+                               unseen = -3.6109179126442243,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 35},+                   koData =+                     ClassData{prior = -1.9218125974762528,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.1972245773362196),+                                    ("hh:mmhh:mm", -1.0986122886681098),+                                    ("hourhour", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 5}}),+       ("between <datetime> and <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.2039728043259361),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.3025850929940455),+                                    ("hh:mmhh:mm", -1.2039728043259361),+                                    ("hourhour", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.5108256237659907, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.466337068793427),+                                    ("minuteminute", -1.8718021769015913),+                                    ("hourhour", -2.5649493574615367),+                                    ("minutehour", -1.466337068793427),+                                    ("hh:mmintersect", -1.8718021769015913),+                                    ("time-of-day (latent)<time> <part-of-day>",+                                     -2.5649493574615367)],+                               n = 9}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = -0.7308875085427924,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.8870696490323797),+                                    ("time-of-day (latent)", -1.2992829841302609),+                                    ("until <time-of-day>", -2.803360380906535),+                                    ("hour", -0.8574502318512216)],+                               n = 13},+                   koData =+                     ClassData{prior = -0.6567795363890705, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> quarter", -2.8622008809294686),+                                    ("time-of-day (latent)", -0.9903987040278769),+                                    ("hour", -0.916290731874155), ("minute", -2.8622008809294686),+                                    ("after <time-of-day>", -2.8622008809294686)],+                               n = 14}}),+       ("three-quarters of an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.8690378470236094, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -0.5436154465889815, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.2992829841302609),+                                    ("ordinals (first..19th)quarter (grain)", -1.2992829841302609),+                                    ("quarter", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("ordinals (first..19th)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037)],+                               n = 2}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.5171347929592555, unseen = -6.049733455231958,+                               likelihoods =+                                 HashMap.fromList+                                   [("u <named-day><day-of-month>(ordinal) <named-month>",+                                     -5.354224998486333),+                                    ("hourday", -4.948759890378168),+                                    ("dd.mm<time-of-day> o'clock", -5.354224998486333),+                                    ("dayhour", -2.680076349059804),+                                    ("daymonth", -3.5624655292582776),+                                    ("u <named-day><named-month> <day-of-month> (ordinal)",+                                     -5.354224998486333),+                                    ("monthyear", -3.6494769062479073),+                                    ("christmasyear", -5.354224998486333),+                                    ("u <named-day><time-of-day> o'clock", -5.354224998486333),+                                    ("<time> <part-of-day>u <named-day>", -3.9679306373664422),+                                    ("intersectat <time-of-day>", -5.354224998486333),+                                    ("day before yesterdayat <time-of-day>", -4.661077817926388),+                                    ("between <time-of-day> and <time-of-day> (interval)u <named-day>",+                                     -4.661077817926388),+                                    ("between <datetime> and <datetime> (interval)u <named-day>",+                                     -4.661077817926388),+                                    ("last <cycle>u <named-day>", -5.354224998486333),+                                    ("<time-of-day> o'clocktonight", -5.354224998486333),+                                    ("from <datetime> - <datetime> (interval)u <named-day>",+                                     -5.354224998486333),+                                    ("today<time> <part-of-day>", -4.948759890378168),+                                    ("todayat <time-of-day>", -5.354224998486333),+                                    ("from <time-of-day> - <time-of-day> (interval)u <named-day>",+                                     -5.354224998486333),+                                    ("next <cycle>u <named-day>", -5.354224998486333),+                                    ("named-dayhh:mm", -5.354224998486333),+                                    ("dayday", -3.1029331998798373),+                                    ("hourhour", -5.354224998486333),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -4.948759890378168),+                                    ("intersectnamed-month", -4.437934266612178),+                                    ("dayyear", -3.8501476017100584),+                                    ("named-dayu <named-month>", -4.948759890378168),+                                    ("<time-of-day> o'clocktomorrow", -5.354224998486333),+                                    ("<time-of-day> - <time-of-day> (interval)u <named-day>",+                                     -4.437934266612178),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -4.948759890378168),+                                    ("<datetime> - <datetime> (interval)u <named-day>",+                                     -4.437934266612178),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month>",+                                     -3.9679306373664422),+                                    ("day after tomorrow<time> <part-of-day>", -5.354224998486333),+                                    ("minutemonth", -4.437934266612178),+                                    ("day after tomorrowat <time-of-day>", -4.948759890378168),+                                    ("absorption of , after named day<named-month> <day-of-month> (ordinal)",+                                     -4.437934266612178),+                                    ("named-day<time> timezone", -5.354224998486333),+                                    ("named-monthyear", -3.8501476017100584),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.948759890378168),+                                    ("this <cycle>u <named-day>", -4.948759890378168),+                                    ("last <day-of-week> <time>year", -4.948759890378168),+                                    ("dd.mmat <time-of-day>", -4.948759890378168),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -4.437934266612178),+                                    ("intersect<named-month> <day-of-month> (ordinal)",+                                     -4.948759890378168),+                                    ("named-daynext <cycle>", -5.354224998486333),+                                    ("named-dayintersect", -5.354224998486333),+                                    ("day before yesterday<time-of-day> o'clock",+                                     -5.354224998486333),+                                    ("<time> <part-of-day><named-day> <day-of-month> (ordinal)",+                                     -4.437934266612178),+                                    ("dayminute", -3.274783456806497),+                                    ("u <named-day>at <time-of-day>", -4.948759890378168),+                                    ("<time> <part-of-day>intersect", -3.4824228215847413),+                                    ("u <named-day><time> <part-of-day>", -4.948759890378168),+                                    ("intersectyear", -5.354224998486333),+                                    ("<ordinal> <cycle> of <time>year", -5.354224998486333),+                                    ("minuteday", -2.0583881324820035),+                                    ("absorption of , after named dayintersect",+                                     -5.354224998486333),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -4.661077817926388),+                                    ("<time> <part-of-day>intersect by \",\"", -4.437934266612178),+                                    ("named-day<time> <part-of-day>", -4.437934266612178),+                                    ("named-dayat <time-of-day>", -4.948759890378168),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -4.661077817926388),+                                    ("intersect by \",\"at <time-of-day>", -4.437934266612178),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -4.255612709818223),+                                    ("yearat <time-of-day>", -5.354224998486333),+                                    ("<time> <part-of-day>absorption of , after named day",+                                     -4.661077817926388),+                                    ("todaytonight", -5.354224998486333),+                                    ("weekday", -4.437934266612178),+                                    ("named-day<time-of-day> o'clock", -5.354224998486333),+                                    ("dayweek", -5.354224998486333),+                                    ("weekyear", -4.948759890378168),+                                    ("<named-day> <day-of-month> (ordinal)named-month",+                                     -3.8501476017100584),+                                    ("u <named-day><named-month> <day-of-month> (non ordinal)",+                                     -5.354224998486333),+                                    ("u <named-month>year", -4.948759890378168),+                                    ("last <cycle> of <time>year", -4.948759890378168),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -5.354224998486333),+                                    ("yearminute", -5.354224998486333)],+                               n = 158},+                   koData =+                     ClassData{prior = -0.906900991524316, unseen = -5.7745515455444085,+                               likelihoods =+                                 HashMap.fromList+                                   [("since <time-of-day>by <time>", -4.385146762010125),+                                    ("year<time-of-day> - <time-of-day> (interval)",+                                     -5.07829394257007),+                                    ("hourday", -4.162003210695915),+                                    ("dayhour", -3.1323837935147574),+                                    ("named-monthnamed-day", -3.979681653901961),+                                    ("daymonth", -2.9382277790737996),+                                    ("monthday", -3.69199958145018),+                                    ("monthyear", -3.4688560301359703),+                                    ("yearhour", -4.672828834461907),+                                    ("named-month<hour-of-day> <integer> (as relative minutes)",+                                     -5.07829394257007),+                                    ("hh:mmu <named-day>", -3.979681653901961),+                                    ("last <time>today", -4.385146762010125),+                                    ("intersectat <time-of-day>", -5.07829394257007),+                                    ("named-daysince <time-of-day>", -4.162003210695915),+                                    ("until <time-of-day>u <named-day>", -5.07829394257007),+                                    ("since <time-of-day>u <named-day>", -4.672828834461907),+                                    ("<time> <part-of-day>named-day", -5.07829394257007),+                                    ("dayday", -3.979681653901961),+                                    ("<time> <part-of-day>at <time-of-day>", -5.07829394257007),+                                    ("named-monthnamed-month", -4.385146762010125),+                                    ("monthmonth", -4.162003210695915),+                                    ("hourhour", -5.07829394257007),+                                    ("intersectnamed-month", -4.672828834461907),+                                    ("dayyear", -4.385146762010125),+                                    ("named-dayu <named-month>", -4.162003210695915),+                                    ("<time-of-day> - <time-of-day> (interval)u <named-day>",+                                     -5.07829394257007),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -4.672828834461907),+                                    ("monthminute", -4.672828834461907),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month>",+                                     -5.07829394257007),+                                    ("minutemonth", -4.672828834461907),+                                    ("absorption of , after named day<named-month> <day-of-month> (ordinal)",+                                     -5.07829394257007),+                                    ("intersect<time-of-day> - <time-of-day> (interval)",+                                     -5.07829394257007),+                                    ("named-monthyear", -4.385146762010125),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.385146762010125),+                                    ("absorption of , after named daynamed-month",+                                     -3.979681653901961),+                                    ("intersect by \",\"<time-of-day> - <time-of-day> (interval)",+                                     -4.162003210695915),+                                    ("named-dayafter <time-of-day>", -4.162003210695915),+                                    ("named-dayintersect", -4.385146762010125),+                                    ("dayminute", -3.0633909220278057),+                                    ("<time> <part-of-day>intersect", -4.672828834461907),+                                    ("intersectyear", -4.162003210695915),+                                    ("after <time-of-day>by <time>", -4.385146762010125),+                                    ("minuteday", -3.0633909220278057),+                                    ("absorption of , after named dayintersect", -5.07829394257007),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -4.672828834461907),+                                    ("named-monthnumeral to|till|before <integer> (hour-of-day)",+                                     -5.07829394257007),+                                    ("<time> <part-of-day>intersect by \",\"", -5.07829394257007),+                                    ("named-day<time> <part-of-day>", -4.672828834461907),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -4.385146762010125),+                                    ("intersect by \",\"at <time-of-day>", -4.162003210695915),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -5.07829394257007),+                                    ("yearat <time-of-day>", -5.07829394257007),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -4.672828834461907),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -4.672828834461907),+                                    ("u <named-day>named-month", -5.07829394257007),+                                    ("<named-day> <day-of-month> (ordinal)named-month",+                                     -5.07829394257007),+                                    ("after <time-of-day>u <named-day>", -4.672828834461907),+                                    ("named-monthintersect", -5.07829394257007),+                                    ("hh:mmby <time>", -4.385146762010125),+                                    ("u <named-month>year", -3.979681653901961),+                                    ("minutesecond", -3.4688560301359703),+                                    ("yearminute", -4.672828834461907)],+                               n = 107}}),+       ("early morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7047480922384253),+                                    ("ordinals (first..19th)week (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (first..19th)day (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (first..19th)week (grain)intersect",+                                     -1.7047480922384253),+                                    ("weekmonth", -1.2992829841302609)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.252762968495368),+                                    ("hh:mmhh:mm", -1.252762968495368)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.5040773967762742),+                                    ("minuteminute", -1.5040773967762742),+                                    ("minutehour", -1.5040773967762742),+                                    ("hh:mmintersect", -1.5040773967762742)],+                               n = 2}}),+       ("day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.7047480922384253),+                                    ("month (grain)", -1.9924301646902063),+                                    ("year (grain)", -2.3978952727983707),+                                    ("week (grain)", -1.7047480922384253),+                                    ("quarter", -2.3978952727983707), ("year", -2.3978952727983707),+                                    ("month", -1.9924301646902063),+                                    ("quarter (grain)", -2.3978952727983707)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("hh:mmhh:mm", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.0986122886681098),+                                    ("minutehour", -1.0986122886681098)],+                               n = 1}}),+       ("integer 21..99",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)integer (numeric)", 0.0)],+                               n = 1}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2}}),+       ("prije <duration>",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003), ("day", -1.8971199848858813),+                                    ("year", -2.3025850929940455),+                                    ("<integer> <unit-of-duration>", -0.916290731874155),+                                    ("month", -2.3025850929940455)],+                               n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -1.3862943611198906),+                                    ("hour", -1.3862943611198906)],+                               n = 1}}),+       ("evening|night",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.8472978603872037),+                                    ("ordinals (first..19th)quarter (grain)year",+                                     -1.252762968495368),+                                    ("ordinal (digits)quarter (grain)year", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numeral to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = -1.791759469228055, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (0..19)noon", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.1823215567939546, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7731898882334817),+                                    ("integer (numeric)time-of-day (latent)", -0.7731898882334817)],+                               n = 5}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -0.6931471805599453), ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a pair",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7884573603642702),+                                    ("ordinals (first..19th)named-dayintersect",+                                     -1.0116009116784799),+                                    ("ordinals (first..19th)named-daynamed-month",+                                     -1.7047480922384253)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.8109302162163288),+                                    ("ordinals (first..19th)named-daynamed-month",+                                     -0.8109302162163288)],+                               n = 3}}),+       ("<hour-of-day> quarter",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = -0.25593337413720063,+                               unseen = -3.912023005428146,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 48},+                   koData =+                     ClassData{prior = -1.488077055429833, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.258096538021482,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 24},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("valentine's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <day-of-week> <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.6739764335716716),+                                    ("daymonth", -0.8266785731844679),+                                    ("named-dayu <named-month>", -1.6739764335716716),+                                    ("named-dayintersect", -1.6739764335716716)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("evening|night", -1.8718021769015913),+                                    ("afternoon", -1.466337068793427),+                                    ("hour", -0.9555114450274363),+                                    ("morning", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.252762968495368),+                                    ("late night", -1.252762968495368)],+                               n = 1}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -4.652001563489282e-2,+                               unseen = -3.828641396489095,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.916290731874155),+                                    ("month", -0.7156200364120039),+                                    ("ordinals (first..19th)named-month", -2.1972245773362196)],+                               n = 21},+                   koData =+                     ClassData{prior = -3.0910424533583156, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.916290731874155),+                                    ("month", -0.916290731874155)],+                               n = 1}}),+       ("numbers i",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList [("integer (20..90)integer (0..19)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 11}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.3862943611198906),+                                    ("day", -1.3862943611198906),+                                    ("named-day", -1.3862943611198906),+                                    ("month", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by <time>",+        Classifier{okData =+                     ClassData{prior = -2.70805020110221, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -1.6094379124341003),+                                    ("midnight|EOD|end of day", -1.6094379124341003)],+                               n = 1},+                   koData =+                     ClassData{prior = -6.899287148695143e-2,+                               unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.4849066497880004),+                                    ("intersect", -2.890371757896165),+                                    ("time-of-day (latent)", -1.6376087894007967),+                                    ("hh:mm", -2.1972245773362196), ("noon", -2.4849066497880004),+                                    ("hour", -1.1856236656577395), ("minute", -1.9740810260220096)],+                               n = 14}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> from now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("year", -1.252762968495368),+                                    ("<integer> <unit-of-duration>", -0.8472978603872037),+                                    ("minute", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8718021769015913),+                                    ("month (grain)", -2.5649493574615367),+                                    ("year (grain)", -2.5649493574615367),+                                    ("week (grain)", -1.8718021769015913),+                                    ("day", -2.5649493574615367), ("quarter", -2.159484249353372),+                                    ("year", -2.5649493574615367), ("month", -2.5649493574615367),+                                    ("quarter (grain)", -2.159484249353372),+                                    ("day (grain)", -2.5649493574615367)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> half",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.7047480922384253),+                                    ("time-of-day (latent)", -1.0116009116784799),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.8109302162163288),+                                    ("hour", -0.8109302162163288)],+                               n = 3}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.9444616088408514, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2231435513142097),+                                    ("integer (0..19)", -2.0794415416798357)],+                               n = 35},+                   koData =+                     ClassData{prior = -0.49247648509779407,+                               unseen = -4.110873864173311,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.4307829160924542),+                                    ("integer (20..90)", -2.995732273553991),+                                    ("few", -3.4011973816621555),+                                    ("integer (0..19)", -1.455287232606842),+                                    ("a pair", -3.4011973816621555)],+                               n = 55}}),+       ("for <duration>",+        Classifier{okData =+                     ClassData{prior = -0.11441035117774422,+                               unseen = -4.3694478524670215,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9704144655697013),+                                    ("three-quarters of an hour", -2.7472709142554916),+                                    ("number.number hours", -3.6635616461296463),+                                    ("second", -3.6635616461296463), ("day", -2.5649493574615367),+                                    ("half an hour", -2.5649493574615367),+                                    ("year", -3.6635616461296463),+                                    ("<integer> <unit-of-duration>", -1.221214610760442),+                                    ("hour", -2.4107986776342782), ("month", -3.6635616461296463),+                                    ("minute", -1.5234954826333758),+                                    ("about <duration>", -3.6635616461296463)],+                               n = 33},+                   koData =+                     ClassData{prior = -2.2246235515243336, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -1.3862943611198906),+                                    ("hour", -1.3862943611198906)],+                               n = 4}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.2006706954621511, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 18},+                   koData =+                     ClassData{prior = -1.7047480922384253, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -4.5217885770490405,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.5649493574615367),+                                    ("integer (0..19)year (grain)", -3.1245651453969594),+                                    ("integer (numeric)day (grain)", -2.431417964837014),+                                    ("integer (0..19)hour (grain)", -3.817712325956905),+                                    ("second", -3.817712325956905),+                                    ("a pairhour (grain)", -3.817712325956905),+                                    ("integer (numeric)year (grain)", -3.817712325956905),+                                    ("day", -2.3136349291806306), ("year", -2.9014215940827497),+                                    ("integer (numeric)week (grain)", -3.817712325956905),+                                    ("integer (0..19)month (grain)", -3.41224721784874),+                                    ("integer (0..19)second (grain)", -3.817712325956905),+                                    ("hour", -2.5649493574615367), ("month", -3.41224721784874),+                                    ("integer (numeric)minute (grain)", -2.7191000372887952),+                                    ("integer (0..19)minute (grain)", -3.817712325956905),+                                    ("fewhour (grain)", -3.817712325956905),+                                    ("minute", -2.5649493574615367),+                                    ("integer (numeric)hour (grain)", -3.1245651453969594),+                                    ("integer (0..19)day (grain)", -3.817712325956905),+                                    ("integer (0..19)week (grain)", -2.7191000372887952)],+                               n = 33},+                   koData =+                     ClassData{prior = -0.4700036292457356, unseen = -4.912654885736052,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.959364629383116),+                                    ("integer (0..19)year (grain)", -3.8066624897703196),+                                    ("integer (numeric)day (grain)", -3.518980417318539),+                                    ("fewday (grain)", -4.212127597878484),+                                    ("integer (0..19)hour (grain)", -2.959364629383116),+                                    ("second", -3.295836866004329),+                                    ("numbers ihour (grain)", -3.8066624897703196),+                                    ("integer (numeric)second (grain)", -3.8066624897703196),+                                    ("integer (numeric)year (grain)", -3.8066624897703196),+                                    ("day", -2.959364629383116), ("year", -3.295836866004329),+                                    ("integer (numeric)week (grain)", -3.295836866004329),+                                    ("integer (0..19)month (grain)", -3.8066624897703196),+                                    ("integer (0..19)second (grain)", -3.8066624897703196),+                                    ("hour", -1.5730702682632256), ("month", -3.295836866004329),+                                    ("integer (numeric)minute (grain)", -3.8066624897703196),+                                    ("integer (0..19)minute (grain)", -3.8066624897703196),+                                    ("integer (numeric)month (grain)", -3.8066624897703196),+                                    ("minute", -3.295836866004329),+                                    ("integer (numeric)hour (grain)", -1.9095425048844386),+                                    ("integer (0..19)day (grain)", -3.8066624897703196),+                                    ("integer (0..19)week (grain)", -3.8066624897703196)],+                               n = 55}}),+       ("ordinals (first..19th)",+        Classifier{okData =+                     ClassData{prior = -6.899287148695143e-2,+                               unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -2.70805020110221, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<duration> after <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>christmas", -1.7047480922384253),+                                    ("yearday", -1.7047480922384253),+                                    ("minutesecond", -1.7047480922384253),+                                    ("<integer> <unit-of-duration>now", -1.7047480922384253)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter of an hourtime-of-day (latent)", -1.7047480922384253),+                                    ("minutehour", -1.2992829841302609),+                                    ("quarter of an hour<time> <part-of-day>",+                                     -1.7047480922384253)],+                               n = 2}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.35667494393873245,+                               unseen = -4.820281565605037,+                               likelihoods =+                                 HashMap.fromList+                                   [("u <named-day><day-of-month>(ordinal) <named-month>",+                                     -4.119037174812472),+                                    ("<named-month> <day-of-month> (ordinal)intersect",+                                     -4.119037174812472),+                                    ("u <named-day><named-month> <day-of-month> (ordinal)",+                                     -4.119037174812472),+                                    ("intersecthh:mm", -4.119037174812472),+                                    ("intersect by \",\"year", -3.713572066704308),+                                    ("dayday", -2.0395956331326364),+                                    ("intersect by \",\"hh:mm", -3.202746442938317),+                                    ("intersect by \",\"intersect by \",\"", -4.119037174812472),+                                    ("named-dayintersect by \",\"", -3.0204248861443626),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -4.119037174812472),+                                    ("named-day<named-month> <day-of-month> (ordinal)",+                                     -3.4258899942525267),+                                    ("dayyear", -2.7327428136925813),+                                    ("<named-month> <day-of-month> (ordinal)intersect by \",\"",+                                     -4.119037174812472),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -4.119037174812472),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -4.119037174812472),+                                    ("intersect<day-of-month>(ordinal) <named-month>",+                                     -3.713572066704308),+                                    ("intersect<named-month> <day-of-month> (ordinal)",+                                     -4.119037174812472),+                                    ("intersect by \",\"intersect", -4.119037174812472),+                                    ("named-dayintersect", -4.119037174812472),+                                    ("intersectintersect by \",\"", -4.119037174812472),+                                    ("dayminute", -2.0395956331326364),+                                    ("intersectyear", -3.713572066704308),+                                    ("minuteday", -3.202746442938317),+                                    ("yearhh:mm", -4.119037174812472),+                                    ("intersectintersect", -4.119037174812472),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -2.866274206317104),+                                    ("u <named-day><named-month> <day-of-month> (non ordinal)",+                                     -4.119037174812472),+                                    ("<named-month> <day-of-month> (ordinal)year",+                                     -3.713572066704308),+                                    ("yearminute", -4.119037174812472)],+                               n = 42},+                   koData =+                     ClassData{prior = -1.2039728043259361, unseen = -4.330733340286331,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.70805020110221),+                                    ("hourday", -3.624340932976365),+                                    ("<named-month> <day-of-month> (ordinal)intersect",+                                     -3.624340932976365),+                                    ("dayhour", -2.5257286443082556),+                                    ("daymonth", -2.5257286443082556),+                                    ("monthyear", -3.624340932976365),+                                    ("dayday", -2.5257286443082556),+                                    ("named-dayintersect by \",\"", -3.624340932976365),+                                    ("named-day<named-month> <day-of-month> (ordinal)",+                                     -3.624340932976365),+                                    ("intersectnamed-month", -3.624340932976365),+                                    ("minutemonth", -3.624340932976365),+                                    ("at <time-of-day><day-of-month>(ordinal) <named-month>",+                                     -3.624340932976365),+                                    ("named-monthyear", -3.624340932976365),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.9311937524164198),+                                    ("intersect by \",\"intersect", -3.624340932976365),+                                    ("named-dayintersect", -3.624340932976365),+                                    ("intersectintersect", -3.624340932976365),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -3.624340932976365),+                                    ("u <named-day>named-month", -3.624340932976365)],+                               n = 18}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -2.7398974188114388e-2,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36},+                   koData =+                     ClassData{prior = -3.6109179126442243,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = -1.4815085785140587e-2,+                               unseen = -4.23410650459726,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 67},+                   koData =+                     ClassData{prior = -4.219507705176107, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter of an hour",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("u <named-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("absorption of , after named day", -2.3978952727983707),+                                    ("day", -0.723918839226699),+                                    ("named-day", -0.8574502318512216)],+                               n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-day> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("absorption of , after named dayordinal (digits)",+                                     -1.0116009116784799),+                                    ("named-dayordinal (digits)", -2.3978952727983707),+                                    ("day", -0.7884573603642702),+                                    ("u <named-day>ordinal (digits)", -2.3978952727983707)],+                               n = 9},+                   koData =+                     ClassData{prior = -2.3025850929940455,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("absorption of , after named dayordinal (digits)",+                                     -1.0986122886681098),+                                    ("day", -1.0986122886681098)],+                               n = 1}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -1.7047480922384253, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("evening|night", -2.0149030205422647),+                                    ("day", -1.6094379124341003),+                                    ("named-day", -1.6094379124341003),+                                    ("hour", -1.6094379124341003),+                                    ("week-end", -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.2006706954621511, unseen = -3.784189633918261,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clock", -3.068052935133617),+                                    ("time-of-day (latent)", -0.8708283577973976),+                                    ("hour", -0.8167611365271219)],+                               n = 18}}),+       ("since <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -2.772588722239781, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mm", -1.7047480922384253),+                                    ("minute", -1.7047480922384253)],+                               n = 1},+                   koData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -3.6888794541139363,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.9704144655697013),+                                    ("intersect", -1.8718021769015913),+                                    ("second", -2.0541237336955462),+                                    ("numeral to|till|before <integer> (hour-of-day)",+                                     -2.9704144655697013),+                                    ("now", -2.9704144655697013), ("hh:mm", -2.277267285009756),+                                    ("<datetime> - <datetime> (interval)", -2.5649493574615367),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -2.5649493574615367),+                                    ("minute", -1.1786549963416462)],+                               n = 15}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.2039728043259361, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clock", -1.8718021769015913),+                                    ("time-of-day (latent)", -1.466337068793427),+                                    ("hour", -1.1786549963416462)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.35667494393873245,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -2.3513752571634776),+                                    ("hh:mm", -1.6582280766035324), ("noon", -1.9459101490553135),+                                    ("hour", -1.4350845252893227),+                                    ("midnight|EOD|end of day", -2.3513752571634776),+                                    ("minute", -1.6582280766035324)],+                               n = 7}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (0..19)", 0.0)],+                               n = 1}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("late night",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("midnight|EOD|end of day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.25131442828090605,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -2.3025850929940455),+                                    ("day", -1.0498221244986778),+                                    ("named-day", -1.0498221244986778),+                                    ("month", -2.3025850929940455)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.5040773967762742,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clock", -1.2039728043259361),+                                    ("hour", -1.2039728043259361)],+                               n = 2}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("month (grain)", -2.3025850929940455),+                                    ("year (grain)", -1.8971199848858813),+                                    ("week (grain)", -1.3862943611198906),+                                    ("year", -1.8971199848858813), ("month", -2.3025850929940455)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6026896854443837),+                                    ("integer (0..19)year (grain)", -3.295836866004329),+                                    ("integer (numeric)day (grain)", -3.295836866004329),+                                    ("fewday (grain)", -3.295836866004329),+                                    ("integer (0..19)hour (grain)", -3.295836866004329),+                                    ("second", -2.890371757896165),+                                    ("integer (numeric)second (grain)", -3.295836866004329),+                                    ("integer (numeric)year (grain)", -3.295836866004329),+                                    ("day", -2.6026896854443837), ("year", -2.890371757896165),+                                    ("integer (numeric)week (grain)", -2.890371757896165),+                                    ("integer (0..19)month (grain)", -3.295836866004329),+                                    ("integer (0..19)second (grain)", -3.295836866004329),+                                    ("hour", -2.890371757896165), ("month", -2.890371757896165),+                                    ("integer (numeric)minute (grain)", -3.295836866004329),+                                    ("integer (0..19)minute (grain)", -3.295836866004329),+                                    ("integer (numeric)month (grain)", -3.295836866004329),+                                    ("minute", -2.890371757896165),+                                    ("integer (numeric)hour (grain)", -3.295836866004329),+                                    ("integer (0..19)day (grain)", -3.295836866004329),+                                    ("integer (0..19)week (grain)", -3.295836866004329)],+                               n = 16},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("halloween day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by the end of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("today", -2.0794415416798357),+                                    ("next <cycle>", -2.0794415416798357),+                                    ("day", -1.3862943611198906),+                                    ("this <cycle>", -1.6739764335716716),+                                    ("month", -1.6739764335716716),+                                    ("this <time>", -2.0794415416798357)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.343805421853684,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9444389791664407),+                                    ("three-quarters of an hour", -2.7212954278522306),+                                    ("number.number hours", -3.6375861597263857),+                                    ("second", -3.6375861597263857), ("day", -2.538973871058276),+                                    ("half an hour", -2.538973871058276),+                                    ("year", -3.6375861597263857),+                                    ("<integer> <unit-of-duration>", -1.2396908869280152),+                                    ("hour", -2.384823191231018), ("month", -3.6375861597263857),+                                    ("minute", -1.55814461804655),+                                    ("about <duration>", -3.6375861597263857)],+                               n = 32},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("since <time-of-day>hh:mm", -2.6741486494265287),+                                    ("minuteminute", -1.4213856809311607),+                                    ("hh:mmhh:mm", -1.7578579175523736),+                                    ("dayday", -2.268683541318364),+                                    ("<named-month> <day-of-month> (non ordinal)<named-month> <day-of-month> (non ordinal)",+                                     -2.268683541318364),+                                    ("after <time-of-day>hh:mm", -2.6741486494265287)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -2.268683541318364),+                                    ("minuteminute", -1.7578579175523736),+                                    ("after <time-of-day>intersect", -2.6741486494265287),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -2.268683541318364),+                                    ("hh:mmintersect", -2.268683541318364),+                                    ("since <time-of-day>intersect", -2.6741486494265287),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -2.268683541318364),+                                    ("yearminute", -2.268683541318364)],+                               n = 8}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("since <time-of-day>hh:mm", -2.4423470353692043),+                                    ("minuteminute", -1.1895840668738362),+                                    ("hh:mmhh:mm", -1.5260563034950494),+                                    ("after <time-of-day>hh:mm", -2.4423470353692043)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.4700036292457356,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("since <time-of-day>time-of-day (latent)", -2.740840023925201),+                                    ("hh:mmtime-of-day (latent)", -1.824549292051046),+                                    ("hourhour", -2.740840023925201),+                                    ("minutehour", -1.1314021114911006),+                                    ("numeral to|till|before <integer> (hour-of-day)time-of-day (latent)",+                                     -2.0476928433652555),+                                    ("at <time-of-day>time-of-day (latent)", -2.740840023925201),+                                    ("after <time-of-day>time-of-day (latent)",+                                     -2.740840023925201)],+                               n = 10}}),+       ("quarter after|past (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.110873864173311,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.70805020110221),+                                    ("integer (0..19)year (grain)", -3.4011973816621555),+                                    ("integer (numeric)day (grain)", -2.995732273553991),+                                    ("integer (0..19)hour (grain)", -3.4011973816621555),+                                    ("second", -2.995732273553991),+                                    ("numbers ihour (grain)", -2.995732273553991),+                                    ("integer (numeric)second (grain)", -3.4011973816621555),+                                    ("integer (numeric)year (grain)", -3.4011973816621555),+                                    ("day", -2.70805020110221), ("year", -2.995732273553991),+                                    ("integer (numeric)week (grain)", -2.995732273553991),+                                    ("integer (0..19)month (grain)", -3.4011973816621555),+                                    ("integer (0..19)second (grain)", -3.4011973816621555),+                                    ("hour", -2.3025850929940455), ("month", -2.995732273553991),+                                    ("integer (numeric)minute (grain)", -3.4011973816621555),+                                    ("integer (0..19)minute (grain)", -3.4011973816621555),+                                    ("integer (numeric)month (grain)", -3.4011973816621555),+                                    ("minute", -2.995732273553991),+                                    ("integer (numeric)hour (grain)", -2.995732273553991),+                                    ("integer (0..19)day (grain)", -3.4011973816621555),+                                    ("integer (0..19)week (grain)", -3.4011973816621555)],+                               n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> after <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..19th)named-dayintersect",+                                     -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (first..19th)named-daychristmas",+                                     -0.916290731874155)],+                               n = 1}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 5}}),+       ("numeral after|past (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("integer (20..90)time-of-day (latent)", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -3.7740327982847086e-2,+                               unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -3.295836866004329, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.540445040947149),+                                    ("week (grain)named-month", -1.9459101490553135),+                                    ("day (grain)intersect", -1.9459101490553135),+                                    ("weekmonth", -1.540445040947149),+                                    ("day (grain)named-month", -1.9459101490553135),+                                    ("week (grain)intersect", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -1.0986122886681098),+                                    ("month", -0.8109302162163288),+                                    ("ordinals (first..19th)named-month", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half <integer> (HR style hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -2.890371757896165, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mm", -1.9459101490553135),+                                    ("minute", -1.9459101490553135)],+                               n = 1},+                   koData =+                     ClassData{prior = -5.715841383994864e-2,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -3.1354942159291497),+                                    ("<time-of-day> o'clock", -3.1354942159291497),+                                    ("intersect", -2.03688192726104),+                                    ("second", -2.2192034840549946),+                                    ("numeral to|till|before <integer> (hour-of-day)",+                                     -3.1354942159291497),+                                    ("now", -3.1354942159291497),+                                    ("time-of-day (latent)", -3.1354942159291497),+                                    ("hh:mm", -2.4423470353692043), ("hour", -2.7300291078209855),+                                    ("<datetime> - <datetime> (interval)", -2.7300291078209855),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -2.7300291078209855),+                                    ("minute", -1.3437347467010947)],+                               n = 17}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 17},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd.mm",+        Classifier{okData =+                     ClassData{prior = -1.8718021769015913,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11}}),+       ("day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -1.6094379124341003),+                                    ("quarter of an hour", -1.0986122886681098),+                                    ("minute", -0.7621400520468967)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter of an hour", -0.7884573603642702),+                                    ("minute", -0.7884573603642702)],+                               n = 4}}),+       ("u <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.7884573603642702,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.6061358035703156, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 6}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 4}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("today", -2.772588722239781), ("season", -2.0794415416798357),+                                    ("evening|night", -2.772588722239781),+                                    ("day", -1.5198257537444133), ("afternoon", -2.772588722239781),+                                    ("named-day", -2.367123614131617),+                                    ("hour", -1.6739764335716716), ("morning", -2.772588722239781),+                                    ("week-end", -2.367123614131617)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.8718021769015913, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.9459101490553135),+                                    ("named-day", -1.9459101490553135),+                                    ("hour", -1.9459101490553135),+                                    ("late night", -1.9459101490553135)],+                               n = 2}}),+       ("<named-month> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("month", -0.6931471805599453),+                                    ("named-monthordinal (digits)", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/ID.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.ID (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/IT.hs view
@@ -0,0 +1,2085 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.IT (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time-of-day> - <time-of-day> <day-of-month> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourhourday", -1.6094379124341003),+                                    ("minuteminuteday", -1.6094379124341003),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)named-day",+                                     -1.6094379124341003),+                                    ("<integer> (latent time-of-day)<integer> (latent time-of-day)named-day",+                                     -1.6094379124341003)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)<integer> (latent time-of-day)named-month",+                                     -1.3862943611198906),+                                    ("hourhourmonth", -1.3862943611198906)],+                               n = 1}}),+       ("midnight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("semaine (grain)", -1.3862943611198906),+                                    ("mois (grain)", -1.3862943611198906),+                                    ("month", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.0986122886681098),+                                    ("hh(:|h)mm (time-of-day)", -1.791759469228055),+                                    ("hour", -1.3862943611198906), ("minute", -1.3862943611198906)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.5510646669461725, unseen = -5.030437921392435,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 151},+                   koData =+                     ClassData{prior = -0.8588143024487628, unseen = -4.727387818712341,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 111}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd[/-]mm",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.6325225587435105,+                               unseen = -4.7535901911063645,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight", -4.051784947803305),+                                    ("<time> timezone", -4.051784947803305),+                                    ("<integer 0 12> del <part of day>", -2.665490586683414),+                                    ("<integer> (latent time-of-day)", -1.5668782980153044),+                                    ("hh(:|h)mm (time-of-day)", -2.1058747987479913),+                                    ("<hour-of-day> and <relative minutes>", -4.051784947803305),+                                    ("noon", -3.6463198396951406),+                                    ("hh <relative-minutes> del pomeriggio(time-of-day)",+                                     -3.6463198396951406),+                                    ("<hour-of-day> minus quart", -4.051784947803305),+                                    ("hour", -1.2185716037470886), ("minute", -1.8004931491968097)],+                               n = 51},+                   koData =+                     ClassData{prior = -0.7576857016975165,+                               unseen = -4.6443908991413725,+                               likelihoods =+                                 HashMap.fromList+                                   [("una", -3.9415818076696905),+                                    ("<integer> (latent time-of-day)", -1.0512100497735257),+                                    ("hh(:|h)mm (time-of-day)", -2.842969519001581),+                                    ("<hour-of-day> and <relative minutes>", -3.536116699561526),+                                    ("<hour-of-day> minus <integer> (as relative minutes)",+                                     -3.9415818076696905),+                                    ("noon", -3.9415818076696905), ("hour", -0.99714282850325),+                                    ("minute", -2.4375044108934163)],+                               n = 45}}),+       ("ann\233e (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dopo le <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.3862943611198906, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight", -2.0149030205422647),+                                    ("<integer> (latent time-of-day)", -1.0986122886681098),+                                    ("hour", -0.916290731874155)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.2876820724517809, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight", -2.8622008809294686),+                                    ("<integer> (latent time-of-day)", -1.0704414117014134),+                                    ("hh(:|h)mm (time-of-day)", -2.169053700369523),+                                    ("hour", -0.9903987040278769), ("minute", -2.169053700369523)],+                               n = 15}}),+       ("seconde (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("stanotte",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("dal <integer> al <integer> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..19)number (0..19)", -0.6931471805599453),+                                    ("integer (numeric)integer (numeric)", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer 0 12> del <part of day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2876820724517809),+                                    ("number (0..19)", -1.3862943611198906)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("una",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("semaine (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4657359027997265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 30},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("il <day-of-month>",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 10},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("mois (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.258096538021482,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 24},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (primo..10)trimestre (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (primo..10)trimestre (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 3}}),+       ("in|entro <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.252762968495368),+                                    ("<integer> <unit-of-duration>", -0.8472978603872037),+                                    ("minute", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2039728043259361),+                                    ("semaine (grain)", -1.2039728043259361),+                                    ("mois (grain)", -1.6094379124341003),+                                    ("month", -1.6094379124341003)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("epifania",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time> ",+        Classifier{okData =+                     ClassData{prior = -2.8622008809294686,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.7047480922384253),+                                    ("named-day", -1.7047480922384253),+                                    ("hour", -1.7047480922384253),+                                    ("week-end", -1.7047480922384253)],+                               n = 2},+                   koData =+                     ClassData{prior = -5.8840500022933465e-2,+                               unseen = -4.304065093204169,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.9582549309731873),+                                    ("intersect by \"di\", \"della\", \"del\"",+                                     -3.1918471524802814),+                                    ("day", -2.344549292093078), ("named-day", -3.1918471524802814),+                                    ("hour", -0.9582549309731873),+                                    ("two time tokens separated by `di`", -3.1918471524802814)],+                               n = 33}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7047480922384253),+                                    ("weekmonth", -1.2992829841302609),+                                    ("ordinals (primo..10)jour (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (primo..10)semaine (grain)named-month",+                                     -1.7047480922384253),+                                    ("ordinals (primo..10)semaine (grain)two time tokens in a row",+                                     -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> last",+        Classifier{okData =+                     ClassData{prior = -1.791759469228055, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.252762968495368), ("named-day", -1.252762968495368)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.1823215567939546, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.6094379124341003),+                                    ("<integer> (latent time-of-day)", -1.3217558399823195),+                                    ("hour", -0.916290731874155)],+                               n = 5}}),+       ("the <ordinal> <cycle> <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinals (primo..10)trimestre (grain)year (1000-2100 not latent)",+                                     -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("verso <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("evening", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("weekday", -0.9808292530117262),+                                    ("semaine (grain)<day-of-month> <named-month>",+                                     -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("semaine (grain)<integer> (latent time-of-day)",+                                     -0.9808292530117262),+                                    ("weekhour", -0.9808292530117262)],+                               n = 2}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in the <part-of-day> of <dim time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -0.9808292530117262),+                                    ("morningnamed-day", -1.3862943611198906),+                                    ("eveningtomorrow", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -0.9808292530117262),+                                    ("nighttomorrow", -0.9808292530117262)],+                               n = 2}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinals (primo..10)trimestre (grain)year (1000-2100 not latent)",+                                     -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("festa della repubblica",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in/after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.4849066497880004),+                                    ("un quarto d'ora", -2.4849066497880004),+                                    ("<integer> <unit-of-duration>", -1.5686159179138452),+                                    ("une <unit-of-duration>", -2.4849066497880004),+                                    ("hour", -2.0794415416798357),+                                    ("mezz'ora", -2.4849066497880004),+                                    ("minute", -1.3862943611198906),+                                    ("tre quarti d'ora", -2.4849066497880004)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("i|le n <cycle> passati|passate",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.219507705176107,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)heure (grain)",+                                     -3.5115454388310208),+                                    ("number (0..19)heure (grain)", -3.5115454388310208),+                                    ("number (0..19)jour (grain)", -2.8183982582710754),+                                    ("second", -3.1060803307228566),+                                    ("integer (numeric)ann\233e (grain)", -3.1060803307228566),+                                    ("integer (numeric)seconde (grain)", -3.5115454388310208),+                                    ("integer (numeric)jour (grain)", -3.1060803307228566),+                                    ("day", -2.412933150162911), ("year", -2.5952547069568657),+                                    ("number (0..19)seconde (grain)", -3.5115454388310208),+                                    ("number (0..19)ann\233e (grain)", -3.1060803307228566),+                                    ("hour", -2.2587824703356527),+                                    ("number (0..19)mois (grain)", -3.1060803307228566),+                                    ("month", -2.412933150162911),+                                    ("integer (numeric)minute (grain)", -3.5115454388310208),+                                    ("integer (numeric)mois (grain)", -2.8183982582710754),+                                    ("minute", -3.1060803307228566),+                                    ("number (0..19)minute (grain)", -3.5115454388310208),+                                    ("integer (numeric)heure (grain)", -2.5952547069568657)],+                               n = 24},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("un quarto d'ora",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("santo stefano",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("entro il <integer>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("stasera",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<integer> (latent time-of-day)",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3184537311185346),+                                    ("number (0..19)", -1.3862943611198906)],+                               n = 41},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -4.454347296253507,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3317773923170052),+                                    ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+                                     -3.3440389678222067),+                                    ("number (0..19)", -1.3981288187668934)],+                               n = 82}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7731898882334817),+                                    ("ordinals (primo..10)named-daynamed-month",+                                     -1.466337068793427),+                                    ("ordinals (primo..10)named-daytwo time tokens in a row",+                                     -1.1786549963416462)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.8109302162163288),+                                    ("ordinals (primo..10)named-daynamed-month",+                                     -0.8109302162163288)],+                               n = 3}}),+       ("a quart to <integer> (as hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -0.6931471805599453), ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> notte",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("new year's eve", -1.8718021769015913),+                                    ("tomorrow", -0.9555114450274363),+                                    ("day", -0.7731898882334817)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = -1.680711831638129e-2,+                               unseen = -4.110873864173311,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 59},+                   koData =+                     ClassData{prior = -4.0943445622221, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("intersect by \"di\", \"della\", \"del\"",+        Classifier{okData =+                     ClassData{prior = -0.41616039722491244,+                               unseen = -4.442651256490317,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)named-day", -3.332204510175204),+                                    ("named-daynamed-month", -3.332204510175204),+                                    ("hourday", -2.4849066497880004),+                                    ("day of month (1st)named-month", -3.7376696182833684),+                                    ("daymonth", -2.3513752571634776),+                                    ("named-daytwo time tokens in a row", -3.7376696182833684),+                                    ("at <time-of-day>named-day", -3.332204510175204),+                                    ("hh(:|h)mm (time-of-day)<day-of-month> <named-month>",+                                     -3.7376696182833684),+                                    ("two time tokens in a rowtwo time tokens in a row",+                                     -3.7376696182833684),+                                    ("dalle <time-of-day> alle <time-of-day> (interval)named-day",+                                     -3.044522437723423),+                                    ("<integer 0 12> del <part of day>tomorrow",+                                     -3.7376696182833684),+                                    ("hh(:|h)mm (time-of-day)two time tokens in a row",+                                     -2.8213788864092133),+                                    ("hh(:|h)mm (time-of-day)<named-day> <day-of-month>",+                                     -3.332204510175204),+                                    ("at <time-of-day>two time tokens in a row",+                                     -3.332204510175204),+                                    ("minuteday", -1.6582280766035324),+                                    ("at <time-of-day><named-day> <day-of-month>",+                                     -3.7376696182833684),+                                    ("dayweek", -3.044522437723423),+                                    ("two time tokens in a rownamed-month", -3.332204510175204),+                                    ("<dim time> al <part-of-day>tomorrow", -3.7376696182833684),+                                    ("named-daythis <cycle>", -3.044522437723423),+                                    ("tra il <datetime> e il <datetime> (interval)named-day",+                                     -3.332204510175204)],+                               n = 31},+                   koData =+                     ClassData{prior = -1.0775588794702773, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)named-day", -2.890371757896165),+                                    ("named-daynamed-month", -2.379546134130174),+                                    ("hourday", -2.1972245773362196),+                                    ("daymonth", -1.9095425048844386),+                                    ("named-daytwo time tokens in a row", -2.6026896854443837),+                                    ("at <time-of-day>named-day", -2.1972245773362196),+                                    ("stanottetomorrow", -2.890371757896165),+                                    ("minuteday", -2.379546134130174)],+                               n = 16}}),+       ("<hour-of-day> and a quart",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2}}),+       ("commemorazione dei defunti",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("valentine's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh(:|h)mm (time-of-day)",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -3.784189633918261,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 42},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("EOY|End of year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.4595323293784402, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -2.639057329615259),+                                    ("hour", -0.7672551527136672), ("evening", -1.1349799328389845),+                                    ("morning", -1.9459101490553135)],+                               n = 12},+                   koData =+                     ClassData{prior = -0.9985288301111273,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8109302162163288), ("evening", -1.791759469228055),+                                    ("morning", -1.0986122886681098)],+                               n = 7}}),+       ("circa per le <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer 0 12> del <part of day>", -1.5040773967762742),+                                    ("<integer> (latent time-of-day)", -1.0986122886681098),+                                    ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("christmas eve",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("festa del lavoro",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("il week-end del <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<day-of-month> <named-month>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2231435513142097),+                                    ("number (0..19)", -1.6094379124341003)],+                               n = 13}}),+       ("entro le <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("il <day-of-month>", -2.639057329615259),+                                    ("<integer> (latent time-of-day)", -2.2335922215070942),+                                    ("named-month", -2.639057329615259),+                                    ("hh(:|h)mm (time-of-day)", -2.639057329615259),+                                    ("EOY|End of year", -2.639057329615259),+                                    ("day", -2.639057329615259), ("year", -2.639057329615259),+                                    ("EOM|End of month", -2.639057329615259),+                                    ("noon", -2.639057329615259), ("hour", -1.9459101490553135),+                                    ("month", -2.2335922215070942), ("minute", -2.639057329615259)],+                               n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -1.9459101490553135),+                                    ("hour", -1.9459101490553135)],+                               n = 1}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -5.406722127027582e-2,+                               unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18},+                   koData =+                     ClassData{prior = -2.9444389791664407,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("domattina",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (primo..10)",+        Classifier{okData =+                     ClassData{prior = -1.0185695809945732, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -0.4480247225269604,+                               unseen = -3.2188758248682006,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 23}}),+       ("the <ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.6931471805599453),+                                    ("ordinals (primo..10)jour (grain)named-month",+                                     -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("gli <n> ultimi <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.8109302162163288),+                                    ("number (0..19)semaine (grain)", -1.5040773967762742),+                                    ("integer (numeric)semaine (grain)", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("tra il <integer> e il <integer> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)integer (numeric)", 0.0)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2809338454620642),+                                    ("ann\233e (grain)", -2.1972245773362196),+                                    ("semaine (grain)", -1.2809338454620642),+                                    ("quarter", -2.1972245773362196), ("year", -2.1972245773362196),+                                    ("trimestre (grain)", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("semaine (grain)", -1.3862943611198906)],+                               n = 1}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("il <cycle> dopo <time>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.5040773967762742),+                                    ("dayday", -1.5040773967762742),+                                    ("mois (grain)two time tokens in a row", -1.5040773967762742),+                                    ("jour (grain)tomorrow", -1.5040773967762742)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.252762968495368),+                                    ("mois (grain)christmas", -1.252762968495368)],+                               n = 1}}),+       ("night",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("tra il <datetime> e il <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8109302162163288, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.466337068793427),+                                    ("at <time-of-day>at <time-of-day>", -0.9555114450274363),+                                    ("hourhour", -1.466337068793427)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.587786664902119, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)<integer> (latent time-of-day)",+                                     -1.3217558399823195),+                                    ("at <time-of-day>at <time-of-day>", -1.6094379124341003),+                                    ("hourhour", -1.3217558399823195),+                                    ("minutehour", -1.6094379124341003)],+                               n = 5}}),+       ("gli ultimi <n> <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.343805421853684,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.2321210516182215),+                                    ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)heure (grain)",+                                     -3.6375861597263857),+                                    ("number (0..19)heure (grain)", -2.9444389791664407),+                                    ("number (0..19)jour (grain)", -3.2321210516182215),+                                    ("second", -3.2321210516182215),+                                    ("integer (numeric)ann\233e (grain)", -2.9444389791664407),+                                    ("integer (numeric)seconde (grain)", -3.6375861597263857),+                                    ("integer (numeric)jour (grain)", -3.2321210516182215),+                                    ("day", -2.7212954278522306), ("year", -2.538973871058276),+                                    ("number (0..19)seconde (grain)", -3.6375861597263857),+                                    ("number (0..19)ann\233e (grain)", -3.2321210516182215),+                                    ("number (0..19)semaine (grain)", -3.6375861597263857),+                                    ("hour", -2.2512917986064953),+                                    ("number (0..19)mois (grain)", -2.9444389791664407),+                                    ("month", -2.538973871058276),+                                    ("integer (numeric)minute (grain)", -3.6375861597263857),+                                    ("integer (numeric)mois (grain)", -3.2321210516182215),+                                    ("minute", -3.2321210516182215),+                                    ("number (0..19)minute (grain)", -3.6375861597263857),+                                    ("integer (numeric)semaine (grain)", -3.6375861597263857),+                                    ("integer (numeric)heure (grain)", -2.9444389791664407)],+                               n = 27},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("le idi di <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (primo..10)trimestre (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (primo..10)trimestre (grain)", -0.6931471805599453),+                                    ("quarter", -0.6931471805599453)],+                               n = 2}}),+       ("<dim time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.5389965007326869, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.1786549963416462),+                                    ("<day-of-month> <named-month>morning", -2.5649493574615367),+                                    ("tomorrowevening", -2.5649493574615367),+                                    ("named-daymorning", -2.159484249353372),+                                    ("tomorrowmorning", -2.5649493574615367),+                                    ("tomorrowlunch", -2.5649493574615367),+                                    ("yesterdayevening", -2.5649493574615367)],+                               n = 7},+                   koData =+                     ClassData{prior = -0.8754687373538999,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.9924301646902063),+                                    ("tomorrownight", -2.3978952727983707),+                                    ("monthhour", -1.7047480922384253),+                                    ("named-monththis <part-of-day>", -1.9924301646902063),+                                    ("tomorrowstanotte", -2.3978952727983707),+                                    ("named-monthmorning", -2.3978952727983707)],+                               n = 5}}),+       ("<hour-of-day> and <relative minutes>",+        Classifier{okData =+                     ClassData{prior = -1.0116009116784799, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>number (20..90)", -1.8718021769015913),+                                    ("<integer> (latent time-of-day)integer (numeric)",+                                     -1.466337068793427),+                                    ("<integer> (latent time-of-day)number (20..90)",+                                     -1.8718021769015913),+                                    ("hour", -0.9555114450274363)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>number (20..90)", -1.845826690498331),+                                    ("<integer> (latent time-of-day)integer (numeric)",+                                     -2.2512917986064953),+                                    ("<integer> (latent time-of-day)number (20..90)",+                                     -1.845826690498331),+                                    ("hour", -0.8649974374866046),+                                    ("<integer> (latent time-of-day)number (0..19)",+                                     -1.845826690498331)],+                               n = 7}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.8109302162163288),+                                    ("named-daytwo time tokens in a row", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-day> <day-of-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayinteger (numeric)", -0.6931471805599453),+                                    ("day", -0.6931471805599453)],+                               n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -2.9444389791664407,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.70805020110221),+                                    ("number (0..19)semaine (grain)", -2.70805020110221),+                                    ("hour", -2.70805020110221),+                                    ("integer (numeric)minute (grain)", -2.3025850929940455),+                                    ("minute", -2.3025850929940455),+                                    ("integer (numeric)heure (grain)", -2.70805020110221)],+                               n = 4},+                   koData =+                     ClassData{prior = -5.406722127027582e-2,+                               unseen = -5.117993812416755,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.3202283191284883),+                                    ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)heure (grain)",+                                     -4.013375499688434),+                                    ("number (0..19)heure (grain)", -3.3202283191284883),+                                    ("number (0..19)jour (grain)", -3.16607763930123),+                                    ("second", -3.0325462466767075),+                                    ("integer (numeric)ann\233e (grain)", -3.16607763930123),+                                    ("integer (numeric)seconde (grain)", -3.7256934272366524),+                                    ("integer (numeric)jour (grain)", -3.16607763930123),+                                    ("day", -2.5470384308950065), ("year", -2.627081138568543),+                                    ("number (0..19)seconde (grain)", -3.5025498759224427),+                                    ("number (0..19)ann\233e (grain)", -3.3202283191284883),+                                    ("number (0..19)semaine (grain)", -4.013375499688434),+                                    ("hour", -2.278774444300327),+                                    ("number (0..19)mois (grain)", -3.0325462466767075),+                                    ("month", -2.403937587254333),+                                    ("integer (numeric)minute (grain)", -3.5025498759224427),+                                    ("integer (numeric)mois (grain)", -3.0325462466767075),+                                    ("minute", -3.0325462466767075),+                                    ("number (0..19)minute (grain)", -3.7256934272366524),+                                    ("integer (numeric)semaine (grain)", -3.7256934272366524),+                                    ("integer (numeric)heure (grain)", -2.8094026953624978)],+                               n = 72}}),+       ("immacolata concezione",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> al <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3746934494414107,+                               unseen = -3.6375861597263857,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.413693335308005),+                                    ("<integer> (latent time-of-day)afternoon", -2.917770732084279),+                                    ("hh(:|h)mm (time-of-day)afternoon", -2.917770732084279),+                                    ("<day-of-month> <named-month>morning", -2.512305623976115),+                                    ("il <day-of-month> <named-month>morning", -2.917770732084279),+                                    ("hourhour", -2.917770732084279),+                                    ("two time tokens in a rowmorning", -2.917770732084279),+                                    ("minutehour", -2.512305623976115),+                                    ("tomorrowevening", -2.917770732084279),+                                    ("named-daymorning", -2.512305623976115),+                                    ("il <time>morning", -2.917770732084279),+                                    ("hh(:|h)mm (time-of-day)morning", -2.917770732084279)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.1631508098056809, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -2.5257286443082556),+                                    ("<integer> (latent time-of-day)afternoon", -2.120263536200091),+                                    ("tomorrownight", -2.5257286443082556),+                                    ("monthhour", -2.120263536200091),+                                    ("hourhour", -2.120263536200091),+                                    ("named-monthmorning", -2.120263536200091)],+                               n = 5}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.290459441148391,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 71},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dal <datetime> al <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.6931471805599453),+                                    ("tomorrownamed-day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dalle <time-of-day> alle <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.35667494393873245,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight<integer> (latent time-of-day)", -2.3978952727983707),+                                    ("minuteminute", -1.7047480922384253),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -1.7047480922384253),+                                    ("<integer> (latent time-of-day)<integer> (latent time-of-day)",+                                     -1.9924301646902063),+                                    ("hourhour", -1.4816045409242156),+                                    ("<integer> (latent time-of-day)una", -2.3978952727983707)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.2039728043259361, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("minutehour", -1.252762968495368),+                                    ("hh(:|h)mm (time-of-day)<integer> (latent time-of-day)",+                                     -1.252762968495368)],+                               n = 3}}),+       ("ferragosto",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day of month (1st)",+        Classifier{okData =+                     ClassData{prior = -9.53101798043249e-2,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -2.3978952727983707,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("number (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.14058195062118944,+                               unseen = -4.007333185232471,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 53},+                   koData =+                     ClassData{prior = -2.031432322493475, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8}}),+       ("year (1000-2100 not latent)",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -2.890371757896165,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 16},+                   koData =+                     ClassData{prior = -1.6094379124341003, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("il <time>",+        Classifier{okData =+                     ClassData{prior = -0.1823215567939546, unseen = -4.060443010546419,+                               likelihoods =+                                 HashMap.fromList+                                   [("dd[/-]mm", -3.349904087274605),+                                    ("<ordinal> quarter", -3.349904087274605),+                                    ("<cycle> next", -3.349904087274605),+                                    ("<ordinal> <cycle> of <time>", -3.349904087274605),+                                    ("<ordinal> quarter <year>", -3.349904087274605),+                                    ("day", -1.3350010667323402), ("quarter", -2.9444389791664407),+                                    ("<dim time> al <part-of-day>", -3.349904087274605),+                                    ("named-day", -3.349904087274605),+                                    ("day of month (1st)", -3.349904087274605),+                                    ("two time tokens in a row", -2.6567569067146595),+                                    ("hour", -2.9444389791664407), ("month", -3.349904087274605),+                                    ("next <time>", -2.9444389791664407),+                                    ("<day-of-month> <named-month>", -2.097141118779237),+                                    ("minute", -3.349904087274605),+                                    ("week-end", -3.349904087274605)],+                               n = 20},+                   koData =+                     ClassData{prior = -1.791759469228055, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> quarter", -2.5257286443082556),+                                    ("day", -2.5257286443082556), ("quarter", -2.5257286443082556),+                                    ("two time tokens in a row", -2.5257286443082556),+                                    ("hour", -2.120263536200091),+                                    ("<day-of-month> <named-month>", -2.5257286443082556),+                                    ("week-end", -2.5257286443082556)],+                               n = 4}}),+       ("entro <time>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -2.4423470353692043),+                                    ("il <day-of-month>", -2.4423470353692043),+                                    ("named-month", -2.4423470353692043),+                                    ("EOY|End of year", -2.4423470353692043),+                                    ("day", -2.4423470353692043), ("year", -2.4423470353692043),+                                    ("EOM|End of month", -2.4423470353692043),+                                    ("noon", -2.4423470353692043), ("hour", -2.4423470353692043),+                                    ("month", -2.03688192726104), ("minute", -2.4423470353692043)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.8718021769015913),+                                    ("hour", -1.8718021769015913)],+                               n = 1}}),+       ("trimestre (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ognissanti",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> minus <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("noonnumber (0..19)", -1.0986122886681098),+                                    ("at <time-of-day>number (0..19)", -1.5040773967762742),+                                    ("hour", -0.8109302162163288)],+                               n = 3}}),+       ("une <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("heure (grain)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <cycle> ",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.7047480922384253),+                                    ("ann\233e (grain)", -2.3978952727983707),+                                    ("semaine (grain)", -1.7047480922384253),+                                    ("mois (grain)", -2.3978952727983707),+                                    ("quarter", -1.9924301646902063), ("year", -2.3978952727983707),+                                    ("trimestre (grain)", -1.9924301646902063),+                                    ("month", -2.3978952727983707)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("EOM|End of month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh quart del pomeriggio(time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two time tokens in a row",+        Classifier{okData =+                     ClassData{prior = -0.3708595789306889, unseen = -5.955837369464831,+                               likelihoods =+                                 HashMap.fromList+                                   [("il <time>named-month", -5.260096153727839),+                                    ("hh(:|h)mm (time-of-day)named-day", -5.260096153727839),+                                    ("intersect by \"di\", \"della\", \"del\"year (1000-2100 not latent)",+                                     -4.854631045619675),+                                    ("named-monthyear (1000-2100 not latent)", -3.5553480614894135),+                                    ("day of month (1st)named-month", -4.566948973167894),+                                    ("dayhour", -3.245193133185574),+                                    ("daymonth", -2.4875074314880576),+                                    ("day of month (1st)intersect by \"di\", \"della\", \"del\"",+                                     -4.566948973167894),+                                    ("monthyear", -3.5553480614894135),+                                    ("day of month (1st)two time tokens in a row",+                                     -4.161483865059729),+                                    ("named-dayentro <time>", -5.260096153727839),+                                    ("named-daytwo time tokens in a row", -4.854631045619675),+                                    ("<ordinal> <cycle> of <time>year (1000-2100 not latent)",+                                     -5.260096153727839),+                                    ("christmasyear (1000-2100 not latent)", -4.854631045619675),+                                    ("<named-day> <day-of-month>two time tokens in a row",+                                     -4.854631045619675),+                                    ("tra il <integer> e il <integer> (interval)named-month",+                                     -4.854631045619675),+                                    ("tomorrowdopo <time>", -5.260096153727839),+                                    ("at <time-of-day>named-day", -5.260096153727839),+                                    ("intersect by \"di\", \"della\", \"del\"<day-of-month> <named-month>",+                                     -4.566948973167894),+                                    ("entro il <integer>named-month", -5.260096153727839),+                                    ("day of month (1st)named-day", -4.161483865059729),+                                    ("dayday", -2.695146796266302),+                                    ("named-daydalle <time-of-day> alle <time-of-day> (interval)",+                                     -4.854631045619675),+                                    ("il <time>year (1000-2100 not latent)", -5.260096153727839),+                                    ("intersect by \"di\", \"della\", \"del\"named-month",+                                     -4.566948973167894),+                                    ("dayyear", -3.120029990231568),+                                    ("tomorrowdalle <time-of-day> alle <time-of-day> (interval)",+                                     -5.260096153727839),+                                    ("hh(:|h)mm (time-of-day)two time tokens in a row",+                                     -4.854631045619675),+                                    ("dd[/-]mmat <time-of-day>", -5.260096153727839),+                                    ("tomorrowdopo le <time-of-day>", -4.854631045619675),+                                    ("monthminute", -4.566948973167894),+                                    ("minutemonth", -3.7560187569515646),+                                    ("named-day<time> timezone", -5.260096153727839),+                                    ("hh(:|h)mm (time-of-day)<named-day> <day-of-month>",+                                     -5.260096153727839),+                                    ("il <day-of-month> <named-month>at <time-of-day>",+                                     -5.260096153727839),+                                    ("named-dayin <named-month>", -4.566948973167894),+                                    ("named-day<day-of-month> <named-month>", -3.6506582412937383),+                                    ("<day-of-month> <named-month>at <time-of-day>",+                                     -4.566948973167894),+                                    ("il <day-of-month> <named-month>year (1000-2100 not latent)",+                                     -5.260096153727839),+                                    ("two time tokens separated by `di`year (1000-2100 not latent)",+                                     -4.854631045619675),+                                    ("last <cycle> of <time>year (1000-2100 not latent)",+                                     -4.566948973167894),+                                    ("day of month (1st)two time tokens separated by `di`",+                                     -4.566948973167894),+                                    ("dal <integer> al <integer> (interval)named-month",+                                     -4.854631045619675),+                                    ("il <day-of-month>named-month", -4.007333185232471),+                                    ("the day after tomorrowat <time-of-day>", -4.854631045619675),+                                    ("two time tokens in a rowyear (1000-2100 not latent)",+                                     -4.566948973167894),+                                    ("il <day-of-month>two time tokens in a row",+                                     -4.854631045619675),+                                    ("at <time-of-day>two time tokens in a row",+                                     -4.854631045619675),+                                    ("dayminute", -2.8622008809294686),+                                    ("two time tokens in a rowat <time-of-day>",+                                     -4.161483865059729),+                                    ("minuteday", -3.0628715763916197),+                                    ("two time tokens separated by `di`<day-of-month> <named-month>",+                                     -4.566948973167894),+                                    ("il <time>at <time-of-day>", -5.260096153727839),+                                    ("named-dayat <time-of-day>", -4.854631045619675),+                                    ("last <day-of-week> of <time>year (1000-2100 not latent)",+                                     -5.260096153727839),+                                    ("immacolata concezioneat <time-of-day>", -5.260096153727839),+                                    ("at <time-of-day><named-day> <day-of-month>",+                                     -5.260096153727839),+                                    ("two time tokens separated by `di`named-month",+                                     -4.566948973167894),+                                    ("weekyear", -4.854631045619675),+                                    ("named-dayentro le <time-of-day>", -5.260096153727839),+                                    ("two time tokens in a rownamed-month", -4.854631045619675),+                                    ("tomorrowat <time-of-day>", -5.260096153727839),+                                    ("two time tokens in a row<day-of-month> <named-month>",+                                     -4.854631045619675),+                                    ("named-daytra il <datetime> e il <datetime> (interval)",+                                     -4.854631045619675),+                                    ("two time tokens in a rowin <named-month>",+                                     -4.566948973167894),+                                    ("<named-day> <day-of-month>named-month", -3.6506582412937383),+                                    ("the day after tomorrowentro le <time-of-day>",+                                     -5.260096153727839),+                                    ("<day-of-month> <named-month>year (1000-2100 not latent)",+                                     -4.854631045619675),+                                    ("named-monthat <time-of-day>", -4.566948973167894),+                                    ("commemorazione dei defuntiat <time-of-day>",+                                     -5.260096153727839),+                                    ("<datetime> - <datetime> (interval)named-day",+                                     -5.260096153727839)],+                               n = 147},+                   koData =+                     ClassData{prior = -1.1716374236829996,+                               unseen = -5.4116460518550396,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>prossimi <unit-of-duration>",+                                     -4.308559482792009),+                                    ("hh(:|h)mm (time-of-day)named-day", -4.7140245909001735),+                                    ("intersect by \"di\", \"della\", \"del\"year (1000-2100 not latent)",+                                     -4.020877410340228),+                                    ("named-monthyear (1000-2100 not latent)", -4.7140245909001735),+                                    ("dayhour", -2.188295946591918),+                                    ("daymonth", -4.7140245909001735),+                                    ("monthday", -4.308559482792009),+                                    ("monthyear", -4.7140245909001735),+                                    ("named-daytwo time tokens in a row", -4.020877410340228),+                                    ("tra il <datetime> e il <datetime> (interval)named-month",+                                     -4.308559482792009),+                                    ("<named-day> <day-of-month>two time tokens in a row",+                                     -4.020877410340228),+                                    ("named-month<day-of-month> <named-month>", -4.308559482792009),+                                    ("monthhour", -3.615412302232064),+                                    ("hourmonth", -4.308559482792009),+                                    ("dayday", -4.7140245909001735),+                                    ("named-daydalle <time-of-day> alle <time-of-day> (interval)",+                                     -4.7140245909001735),+                                    ("named-monththis <part-of-day>", -4.308559482792009),+                                    ("dayyear", -3.2099471941238993),+                                    ("tomorrowdalle <time-of-day> alle <time-of-day> (interval)",+                                     -4.7140245909001735),+                                    ("tomorrowstanotte", -4.7140245909001735),+                                    ("year (1000-2100 not latent)<hour-of-day> <integer> (as relative minutes)",+                                     -4.308559482792009),+                                    ("the <cycle> of <time>named-month", -4.308559482792009),+                                    ("dd[/-]mmat <time-of-day>", -4.7140245909001735),+                                    ("tomorrowdopo le <time-of-day>", -4.308559482792009),+                                    ("monthminute", -4.7140245909001735),+                                    ("minutemonth", -4.308559482792009),+                                    ("named-daydopo <time>", -4.7140245909001735),+                                    ("il <day-of-month> <named-month>at <time-of-day>",+                                     -4.7140245909001735),+                                    ("dopo <time>at <time-of-day>", -4.7140245909001735),+                                    ("<day-of-month> <named-month>at <time-of-day>",+                                     -3.7977338590260183),+                                    ("weekmonth", -4.308559482792009),+                                    ("two time tokens separated by `di`year (1000-2100 not latent)",+                                     -4.020877410340228),+                                    ("hourweek", -4.308559482792009),+                                    ("il <day-of-month>named-month", -4.7140245909001735),+                                    ("the day after tomorrowat <time-of-day>", -4.7140245909001735),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -4.7140245909001735),+                                    ("il <day-of-month>two time tokens in a row",+                                     -4.7140245909001735),+                                    ("dayminute", -2.9222651216721185),+                                    ("two time tokens in a rowat <time-of-day>",+                                     -3.3277302297802827),+                                    ("minuteday", -4.308559482792009),+                                    ("il <time>at <time-of-day>", -4.7140245909001735),+                                    ("named-daydopo le <time-of-day>", -4.020877410340228),+                                    ("named-dayat <time-of-day>", -4.308559482792009),+                                    ("<hour-of-day> <integer> (as relative minutes)named-day",+                                     -4.7140245909001735),+                                    ("tomorrowat <time-of-day>", -4.7140245909001735),+                                    ("named-daytra il <datetime> e il <datetime> (interval)",+                                     -4.7140245909001735),+                                    ("dopo <time>year (1000-2100 not latent)", -4.308559482792009),+                                    ("<hour-of-day> and <relative minutes>named-month",+                                     -4.7140245909001735),+                                    ("named-monthat <time-of-day>", -3.7977338590260183),+                                    ("yearminute", -4.308559482792009)],+                               n = 66}}),+       ("heure (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("jour (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh <relative-minutes> del pomeriggio(time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>number (20..90)", -1.2992829841302609),+                                    ("<integer> (latent time-of-day)number (20..90)",+                                     -1.2992829841302609),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> minus quart",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.5040773967762742),+                                    ("noon", -1.0986122886681098), ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd[/-]mm[/-]yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -2.0794415416798357), ("day", -0.8266785731844679),+                                    ("named-day", -1.1631508098056809),+                                    ("il <time>", -2.0794415416798357)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098)],+                               n = 1}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.304065093204169,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.498699971920336),+                                    ("number (0..19)heure (grain)", -3.597312260588446),+                                    ("number (0..19)jour (grain)", -3.597312260588446),+                                    ("second", -2.9041650800285006),+                                    ("integer (numeric)ann\233e (grain)", -3.597312260588446),+                                    ("integer (numeric)seconde (grain)", -3.597312260588446),+                                    ("integer (numeric)jour (grain)", -3.1918471524802814),+                                    ("day", -2.9041650800285006), ("year", -2.9041650800285006),+                                    ("number (0..19)seconde (grain)", -3.1918471524802814),+                                    ("number (0..19)ann\233e (grain)", -3.1918471524802814),+                                    ("number (0..19)semaine (grain)", -3.1918471524802814),+                                    ("hour", -2.9041650800285006),+                                    ("number (0..19)mois (grain)", -2.9041650800285006),+                                    ("month", -2.344549292093078),+                                    ("integer (numeric)minute (grain)", -3.1918471524802814),+                                    ("integer (numeric)mois (grain)", -2.9041650800285006),+                                    ("minute", -2.9041650800285006),+                                    ("number (0..19)minute (grain)", -3.597312260588446),+                                    ("integer (numeric)semaine (grain)", -2.9041650800285006),+                                    ("integer (numeric)heure (grain)", -3.1918471524802814)],+                               n = 26},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("entro il <duration>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.9808292530117262),+                                    ("semaine (grain)", -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("mois (grain)", -0.9808292530117262),+                                    ("month", -0.9808292530117262)],+                               n = 2}}),+       ("prossimi <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9924301646902063),+                                    ("ann\233e (grain)", -2.3978952727983707),+                                    ("semaine (grain)", -1.9924301646902063),+                                    ("mois (grain)", -1.9924301646902063),+                                    ("day", -1.9924301646902063), ("year", -2.3978952727983707),+                                    ("jour (grain)", -1.9924301646902063),+                                    ("month", -1.9924301646902063)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dopo <time>",+        Classifier{okData =+                     ClassData{prior = -0.9555114450274363, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.845826690498331),+                                    ("day", -1.55814461804655), ("named-day", -2.2512917986064953),+                                    ("day of month (1st)", -2.2512917986064953),+                                    ("the day after tomorrow", -2.2512917986064953),+                                    ("hour", -1.845826690498331)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.48550781578170077,+                               unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("tomorrow", -1.8325814637483102), ("day", -1.1394342831883648),+                                    ("two time tokens in a row", -1.8325814637483102),+                                    ("hour", -2.5257286443082556),+                                    ("christmas", -2.120263536200091)],+                               n = 8}}),+       ("festa della liberazione",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dal <integer",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)", -0.40546510810816444)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.6931471805599453),+                                    ("number (0..19)", -0.6931471805599453)],+                               n = 4}}),+       ("halloween day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.55814461804655),+                                    ("<day-of-month> <named-month><day-of-month> <named-month>",+                                     -1.845826690498331),+                                    ("hh(:|h)mm (time-of-day)hh(:|h)mm (time-of-day)",+                                     -1.55814461804655),+                                    ("dayday", -1.845826690498331)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.845826690498331),+                                    ("named-month<day-of-month> <named-month>", -1.845826690498331),+                                    ("minuteminute", -2.2512917986064953),+                                    ("hh(:|h)mm (time-of-day)two time tokens in a row",+                                     -2.2512917986064953),+                                    ("year (1000-2100 not latent)<hour-of-day> <integer> (as relative minutes)",+                                     -1.845826690498331),+                                    ("yearminute", -1.845826690498331)],+                               n = 5}}),+       ("<day-of-month> <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.1880522315029396, unseen = -4.127134385045092,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.7096764825111559),+                                    ("month", -0.7096764825111559)],+                               n = 29},+                   koData =+                     ClassData{prior = -1.7635885922613588, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..19)named-month", -2.0149030205422647),+                                    ("integer (numeric)named-month", -0.916290731874155),+                                    ("month", -0.7621400520468967)],+                               n = 6}}),+       ("in <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mezz'ora",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> entro le <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -0.8472978603872037),+                                    ("named-daynoon", -1.252762968495368),+                                    ("the day after tomorrow<integer> (latent time-of-day)",+                                     -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> after <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (primo..10)named-daytwo time tokens in a row",+                                     -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.916290731874155),+                                    ("ordinals (primo..10)named-daychristmas", -0.916290731874155)],+                               n = 1}}),+       ("<part-of-day> of <dim time>",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -1.0986122886681098),+                                    ("morningnamed-day", -2.0149030205422647),+                                    ("morning<day-of-month> <named-month>", -1.6094379124341003),+                                    ("eveningtomorrow", -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.5108256237659907, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -0.9985288301111273),+                                    ("stanottetomorrow", -1.845826690498331),+                                    ("nighttomorrow", -1.845826690498331),+                                    ("afternoontomorrow", -1.845826690498331)],+                               n = 6}}),+       ("<dim time> del mattino",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.7047480922384253),+                                    ("<integer> (latent time-of-day)", -1.7047480922384253),+                                    ("hh(:|h)mm (time-of-day)", -1.7047480922384253),+                                    ("hour", -1.2992829841302609), ("minute", -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.2809338454620642),+                                    ("jour (grain)two time tokens in a row", -1.791759469228055),+                                    ("weekmonth", -1.791759469228055),+                                    ("semaine (grain)named-month", -2.1972245773362196),+                                    ("semaine (grain)two time tokens in a row",+                                     -2.1972245773362196),+                                    ("jour (grain)named-month", -1.791759469228055)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two time tokens separated by `di`",+        Classifier{okData =+                     ClassData{prior = -0.4274440148269396, unseen = -4.406719247264253,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)named-day", -3.295836866004329),+                                    ("named-daynamed-month", -3.295836866004329),+                                    ("hourday", -2.4485390056171257),+                                    ("day of month (1st)named-month", -3.7013019741124937),+                                    ("daymonth", -2.315007612992603),+                                    ("named-daytwo time tokens in a row", -3.7013019741124937),+                                    ("at <time-of-day>named-day", -3.295836866004329),+                                    ("two time tokens in a rowtwo time tokens in a row",+                                     -3.7013019741124937),+                                    ("dalle <time-of-day> alle <time-of-day> (interval)named-day",+                                     -3.0081547935525483),+                                    ("<integer 0 12> del <part of day>tomorrow",+                                     -3.7013019741124937),+                                    ("hh(:|h)mm (time-of-day)two time tokens in a row",+                                     -2.7850112422383386),+                                    ("hh(:|h)mm (time-of-day)<named-day> <day-of-month>",+                                     -3.295836866004329),+                                    ("at <time-of-day>two time tokens in a row",+                                     -3.295836866004329),+                                    ("minuteday", -1.6863989535702288),+                                    ("at <time-of-day><named-day> <day-of-month>",+                                     -3.7013019741124937),+                                    ("dayweek", -3.0081547935525483),+                                    ("two time tokens in a rownamed-month", -3.295836866004329),+                                    ("<dim time> al <part-of-day>tomorrow", -3.7013019741124937),+                                    ("named-daythis <cycle>", -3.0081547935525483),+                                    ("tra il <datetime> e il <datetime> (interval)named-day",+                                     -3.295836866004329)],+                               n = 30},+                   koData =+                     ClassData{prior = -1.0560526742493137,+                               unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)named-day", -2.871679624884012),+                                    ("named-daynamed-month", -2.3608540011180215),+                                    ("hourday", -2.178532444324067),+                                    ("daymonth", -1.890850371872286),+                                    ("named-daytwo time tokens in a row", -2.583997552432231),+                                    ("at <time-of-day>named-day", -2.178532444324067),+                                    ("stanottetomorrow", -2.871679624884012),+                                    ("minuteday", -2.3608540011180215)],+                               n = 16}}),+       ("il <day-of-month> <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("fino al <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh(:|h)mm (time-of-day)", -1.791759469228055),+                                    ("EOY|End of year", -1.791759469228055),+                                    ("year", -1.791759469228055),+                                    ("EOM|End of month", -1.791759469228055),+                                    ("month", -1.791759469228055), ("minute", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("right now",+        Classifier{okData =+                     ClassData{prior = -0.8754687373538999,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -0.5389965007326869,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("tre quarti d'ora",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> last",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("ann\233e (grain)", -2.1972245773362196),+                                    ("semaine (grain)", -1.791759469228055),+                                    ("mois (grain)", -1.5040773967762742),+                                    ("year", -2.1972245773362196), ("month", -1.5040773967762742)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("festa del pap\224",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)integer (numeric)",+                                     -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)integer (numeric)",+                                     -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 4}}),+       ("dd-dd <month> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8971199848858813),+                                    ("semaine (grain)", -1.8971199848858813),+                                    ("mois (grain)", -1.8971199848858813),+                                    ("heure (grain)", -1.8971199848858813),+                                    ("hour", -1.8971199848858813), ("month", -1.8971199848858813)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9459101490553135),+                                    ("semaine (grain)", -1.9459101490553135),+                                    ("day", -1.540445040947149),+                                    ("jour (grain)", -1.540445040947149)],+                               n = 3}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -1.8562979903656263), ("day", -1.8562979903656263),+                                    ("hour", -1.1631508098056809), ("evening", -2.772588722239781),+                                    ("morning", -2.0794415416798357),+                                    ("week-end", -1.6739764335716716)],+                               n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/JA.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.JA (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/KO.hs view
@@ -0,0 +1,1458 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.KO (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> am|pm", -1.3862943611198906),+                                    ("hh:mm", -1.3862943611198906), ("hour", -1.3862943611198906),+                                    ("minute", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.4267425065554492, unseen = -4.836281906951478,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 124},+                   koData =+                     ClassData{prior = -1.0573693301340605, unseen = -4.219507705176107,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 66}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect 2 numbers",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList+                                   [("compose by multiplicationinteger (21..99) - TYPE 2",+                                     -0.40546510810816444)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer - TYPE 1: powers of teninteger (21..99) - TYPE 2",+                                     -0.40546510810816444)],+                               n = 1}}),+       ("the day after tomorrow - \45236\51068\47784\47000",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037, unseen = -4.143134726391533,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.1826954058786512),+                                    ("day-of-weekmorning", -3.4339872044851463),+                                    ("yesterdayevening|night", -3.4339872044851463),+                                    ("mm/ddafternoon", -3.4339872044851463),+                                    ("todayafternoon", -3.4339872044851463),+                                    ("dayevening|night", -3.4339872044851463),+                                    ("todayevening|night", -2.740840023925201),+                                    ("daymorning", -3.4339872044851463),+                                    ("intersectevening|night", -3.4339872044851463),+                                    ("next <cycle>evening|night", -3.028522096376982),+                                    ("tomorrowlunch", -3.4339872044851463),+                                    ("intersectmorning", -3.4339872044851463),+                                    ("the day before yesterday - \50634\44536\51228morning",+                                     -3.4339872044851463),+                                    ("tomorrowevening|night", -3.028522096376982),+                                    ("next <cycle>lunch", -3.4339872044851463)],+                               n = 18},+                   koData =+                     ClassData{prior = -0.5596157879354228, unseen = -4.31748811353631,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)lunch", -3.6109179126442243),+                                    ("dayhour", -1.8191584434161694),+                                    ("yearhour", -1.906169820405799),+                                    ("time-of-day (latent)evening|night", -3.6109179126442243),+                                    ("year (latent)evening|night", -2.512305623976115),+                                    ("hourhour", -2.917770732084279),+                                    ("time-of-day (latent)lunch", -3.6109179126442243),+                                    ("intersectafternoon", -2.10684051586795),+                                    ("year (latent)afternoon", -3.20545280453606),+                                    ("day-of-weekafternoon", -3.6109179126442243),+                                    ("next <cycle>evening|night", -3.6109179126442243),+                                    ("time-of-day (latent)afternoon", -3.6109179126442243),+                                    ("year (latent)morning", -3.20545280453606),+                                    ("tomorrowevening|night", -3.6109179126442243)],+                               n = 24}}),+       ("<time> nth <time> - 3\50900 \52395\51704 \54868\50836\51068",+        Classifier{okData =+                     ClassData{prior = -0.6190392084062235, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -0.7537718023763802),+                                    ("intersectordinals (\52395\48264\51704)day-of-week",+                                     -0.8873031950009028),+                                    ("monthordinals (\52395\48264\51704)day-of-week",+                                     -2.1400661634962708)],+                               n = 7},+                   koData =+                     ClassData{prior = -0.7731898882334817, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -0.7621400520468967),+                                    ("monthordinals (\52395\48264\51704)day-of-week",+                                     -0.7621400520468967)],+                               n = 6}}),+       ("the day before yesterday - \50634\44536\51228",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half - \48152",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> \47560\51648\47561 <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersectday-of-week", -1.5040773967762742),+                                    ("monthday", -0.8109302162163288),+                                    ("monthday-of-week", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer - TYPE 1",+        Classifier{okData =+                     ClassData{prior = -1.8523840910444898, unseen = -3.258096538021482,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 24},+                   koData =+                     ClassData{prior = -0.17062551703076334,+                               unseen = -4.875197323201151,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 129}}),+       ("fraction",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)integer (numeric)", -0.6359887667199967),+                                    ("fractioninteger (numeric)", -1.4469189829363254),+                                    ("integer (numeric)fraction", -1.4469189829363254)],+                               n = 14}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -1.241713132308783, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -0.3409265869705932,+                               unseen = -3.5263605246161616,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 32}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.45983651189029134,+                               unseen = -5.958424693029782,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect<hour-of-day> <integer> (as relative minutes)",+                                     -5.262690188904886),+                                    ("intersectday-of-week", -4.164077900236776),+                                    ("year<time> \47560\51648\47561 <cycle>", -4.857225080796721),+                                    ("next <cycle>day-of-week", -4.3463994570307305),+                                    ("dayhour", -2.0240117367405053),+                                    ("monthday", -2.4294768448486694),+                                    ("yearhour", -3.5579420966664603),+                                    ("<time> <part-of-day>time-of-day", -4.3463994570307305),+                                    ("intersectam|pm <time-of-day>", -3.065465611568666),+                                    ("next <cycle><time-of-day> am|pm", -5.262690188904886),+                                    ("next <cycle>am|pm <time-of-day>", -4.857225080796721),+                                    ("yearintersect", -2.96010509591084),+                                    ("day-of-week<datetime> - <datetime> (interval)",+                                     -4.3463994570307305),+                                    ("day-of-week<time-of-day> - <time-of-day> (interval)",+                                     -4.3463994570307305),+                                    ("monthday with korean number - \51068\51068..\44396\51068",+                                     -5.262690188904886),+                                    ("dayday-of-week", -4.3463994570307305),+                                    ("this <cycle>day-of-week", -4.857225080796721),+                                    ("day-of-week<time> timezone", -5.262690188904886),+                                    ("monthhour", -3.5579420966664603),+                                    ("mm/ddam|pm <time-of-day>", -4.56954300834494),+                                    ("todayam|pm <time-of-day>", -4.56954300834494),+                                    ("the day before yesterday - \50634\44536\51228am|pm <time-of-day>",+                                     -4.3463994570307305),+                                    ("dayday", -3.653252276470785),+                                    ("hourhour", -3.7586127921286114),+                                    ("year<time> <ordinal> <cycle>", -5.262690188904886),+                                    ("month<datetime> - <datetime> (interval)", -4.857225080796721),+                                    ("dayam|pm <time-of-day>", -5.262690188904886),+                                    ("day-of-weekam|pm <time-of-day>", -4.56954300834494),+                                    ("time-of-dayafter <time-of-day>", -5.262690188904886),+                                    ("monthminute", -4.857225080796721),+                                    ("hourminute", -4.56954300834494),+                                    ("intersectday", -4.164077900236776),+                                    ("am|pm <time-of-day>after <time-of-day>", -5.262690188904886),+                                    ("last <cycle>day-of-week", -4.56954300834494),+                                    ("month<time> <part-of-day>", -4.857225080796721),+                                    ("yearmonth", -3.122624025408615),+                                    ("dayminute", -3.653252276470785),+                                    ("today<date>\50640", -5.262690188904886),+                                    ("mm/dd<date>\50640", -5.262690188904886),+                                    ("<hour-of-day> <integer> (as relative minutes)seconds",+                                     -5.262690188904886),+                                    ("<time> <part-of-day><date>\50640", -4.857225080796721),+                                    ("monthintersect", -3.653252276470785),+                                    ("year<time> \47560\51648\47561 <day-of-week>",+                                     -5.262690188904886),+                                    ("intersectintersect", -3.4709307196768306),+                                    ("weekday", -3.653252276470785),+                                    ("intersectday with korean number - \51068\51068..\44396\51068",+                                     -4.857225080796721),+                                    ("yearday", -3.4709307196768306),+                                    ("day-of-weekhh:mm", -4.857225080796721),+                                    ("yearweek", -4.857225080796721),+                                    ("minutesecond", -5.262690188904886),+                                    ("<time> <part-of-day><hour-of-day> <integer> (as relative minutes)",+                                     -4.857225080796721),+                                    ("tomorrow<time-of-day> am|pm", -5.262690188904886),+                                    ("tomorrowam|pm <time-of-day>", -4.857225080796721),+                                    ("dayintersect", -4.857225080796721),+                                    ("day-of-weektime-of-day", -5.262690188904886)],+                               n = 173},+                   koData =+                     ClassData{prior = -0.9980075895468108, unseen = -5.616771097666572,+                               likelihoods =+                                 HashMap.fromList+                                   [("year<time> \47560\51648\47561 <cycle>", -4.919980925828125),+                                    ("day-of-weekintersect", -4.919980925828125),+                                    ("dayhour", -2.2809235962128662),+                                    ("daymonth", -4.5145158177199605),+                                    ("monthday", -3.1282214566000697),+                                    ("yearhour", -3.2152328335897),+                                    ("<time> <part-of-day>time-of-day", -3.821368637160015),+                                    ("houryear", -4.22683374526818),+                                    ("day-of-weekafter <time-of-day>", -4.919980925828125),+                                    ("after <time-of-day>by <time> - \44620\51648",+                                     -4.919980925828125),+                                    ("intersectam|pm <time-of-day>", -4.5145158177199605),+                                    ("intersect<time> <part-of-day>", -4.00369019395397),+                                    ("yearintersect", -3.0481787489265337),+                                    ("day-of-week<time-of-day> - <time-of-day> (interval)",+                                     -4.00369019395397),+                                    ("intersectmonth", -4.919980925828125),+                                    ("time-of-day<duration> ago", -4.919980925828125),+                                    ("this <cycle>day-of-week", -4.5145158177199605),+                                    ("intersecttime-of-day", -4.5145158177199605),+                                    ("monthhour", -3.0481787489265337),+                                    ("intersectlast <time>", -4.919980925828125),+                                    ("dayday", -4.00369019395397),+                                    ("hourhour", -2.9740707767728116),+                                    ("month<datetime> - <datetime> (interval)", -4.00369019395397),+                                    ("dayam|pm <time-of-day>", -4.5145158177199605),+                                    ("day-of-weekam|pm <time-of-day>", -4.919980925828125),+                                    ("hourminute", -4.22683374526818),+                                    ("<time-of-day> - <time-of-day> (interval)last <time>",+                                     -4.00369019395397),+                                    ("intersectday", -4.5145158177199605),+                                    ("<datetime> - <datetime> (interval)day", -4.00369019395397),+                                    ("month<time> <part-of-day>", -4.5145158177199605),+                                    ("yearmonth", -4.5145158177199605),+                                    ("dayminute", -4.22683374526818),+                                    ("<hour-of-day> <integer> (as relative minutes)seconds",+                                     -4.22683374526818),+                                    ("<time> <part-of-day><date>\50640", -4.919980925828125),+                                    ("last <time>time-of-day", -4.919980925828125),+                                    ("monthintersect", -3.3105430133940246),+                                    ("hoursecond", -4.919980925828125),+                                    ("year<time> <part-of-day>", -4.5145158177199605),+                                    ("intersectintersect", -3.667217957332757),+                                    ("weekday", -4.5145158177199605),+                                    ("intersectday with korean number - \51068\51068..\44396\51068",+                                     -4.5145158177199605),+                                    ("day<time> <part-of-day>", -4.919980925828125),+                                    ("yearday", -3.821368637160015),+                                    ("day-of-weekhh:mm", -4.919980925828125),+                                    ("<time-of-day> - <time-of-day> (interval)time-of-day",+                                     -4.5145158177199605),+                                    ("intersectafter <time-of-day>", -3.415903529051851),+                                    ("minutesecond", -4.22683374526818),+                                    ("<time> <part-of-day><hour-of-day> <integer> (as relative minutes)",+                                     -4.5145158177199605),+                                    ("dayintersect", -4.919980925828125),+                                    ("mm/ddafter <time-of-day>", -4.919980925828125),+                                    ("todayafter <time-of-day>", -4.919980925828125)],+                               n = 101}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = -1.0608719606852628,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -0.42488319396526597,+                               unseen = -2.9444389791664407,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 17}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.12516314295400605,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("month (grain)", -3.044522437723423),+                                    ("year (grain)", -3.044522437723423),+                                    ("week (grain)", -1.791759469228055),+                                    ("day", -1.791759469228055), ("quarter", -3.044522437723423),+                                    ("year", -3.044522437723423), ("month", -3.044522437723423),+                                    ("quarter (grain)", -3.044522437723423),+                                    ("day (grain)", -1.791759469228055)],+                               n = 15},+                   koData =+                     ClassData{prior = -2.1400661634962708, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -2.0794415416798357),+                                    ("minute (grain)", -2.0794415416798357),+                                    ("minute", -2.0794415416798357),+                                    ("day (grain)", -2.0794415416798357)],+                               n = 2}}),+       ("this <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("day-of-week", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.9315582040049435),+                                    ("integer - TYPE 1", -0.8574502318512216),+                                    ("integer (21..99) - TYPE 2", -2.803360380906535),+                                    ("integer (1..4) - for ordinals", -2.1102132003465894)],+                               n = 29}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening|night",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("Memorial Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (20..90) - TYPE 2 and ordinals",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by <time> - \44620\51648",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("am|pm <time-of-day>", -1.252762968495368),+                                    ("time-of-day", -1.252762968495368),+                                    ("hour", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month>\50640",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("month", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (21..99) - TYPE 2",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (20..90) - TYPE 2 and ordinalsinteger (1..4) - for ordinals",+                                     -1.6094379124341003),+                                    ("integer - TYPE 1: powers of teninteger - TYPE 1",+                                     -1.2039728043259361),+                                    ("compose by multiplicationinteger - TYPE 1",+                                     -1.2039728043259361)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.8109302162163288,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)integer (numeric)", -1.5040773967762742),+                                    ("integer - TYPE 1: powers of teninteger - TYPE 1",+                                     -1.0986122886681098),+                                    ("integer (numeric)integer - TYPE 1", -1.5040773967762742)],+                               n = 4}}),+       ("Independence Movement Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = -0.17589066646366416,+                               unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -1.824549292051046, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5}}),+       ("<year> <1..4>quarter",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearinteger (numeric)quarter (grain)", -0.6931471805599453),+                                    ("yearquarter", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("christmas eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Liberation Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, \47560\51060\45320\49828, or \47560\51060\45208\49828",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 7}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("National Foundation Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (\52395\48264\51704)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (1..4) - for ordinals", -0.35667494393873245),+                                    ("integer (1..10) - TYPE 2", -1.2039728043259361)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day",+        Classifier{okData =+                     ClassData{prior = -0.2657031657330056, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -8.338160893905101e-2),+                                    ("integer - TYPE 1", -2.5257286443082556)],+                               n = 23},+                   koData =+                     ClassData{prior = -1.455287232606842, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.25131442828090605),+                                    ("integer - TYPE 1", -1.5040773967762742)],+                               n = 7}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour (grain)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 7}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("integer (1..4) - for ordinals",+        Classifier{okData =+                     ClassData{prior = -3.7740327982847086e-2,+                               unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 26},+                   koData =+                     ClassData{prior = -3.295836866004329, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<time> <ordinal> <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthordinals (\52395\48264\51704)week (grain)",+                                     -1.252762968495368),+                                    ("monthweek", -0.8472978603872037),+                                    ("intersectordinals (\52395\48264\51704)week (grain)",+                                     -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.3862943611198906),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("week (grain)", -1.3862943611198906),+                                    ("minute (grain)", -2.0794415416798357),+                                    ("minute", -2.0794415416798357)],+                               n = 4}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = -0.6359887667199967,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -0.7537718023763802,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.252762968495368),+                                    ("time-of-day", -1.252762968495368),+                                    ("hour", -0.8472978603872037)],+                               n = 2}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -1.3596261140377293, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.6567795363890705),+                                    ("integer - TYPE 1", -2.6026896854443837),+                                    ("integer (1..4) - for ordinals", -1.6863989535702288),+                                    ("integer (1..10) - TYPE 2", -2.6026896854443837)],+                               n = 19},+                   koData =+                     ClassData{prior = -0.2967319079716989,+                               unseen = -4.1588830833596715,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.052092273033217),+                                    ("integer - TYPE 1", -0.924258901523332),+                                    ("integer (20..90) - TYPE 2 and ordinals", -3.4499875458315876),+                                    ("integer (21..99) - TYPE 2", -3.4499875458315876),+                                    ("integer (1..4) - for ordinals", -2.3513752571634776),+                                    ("integer - TYPE 1: powers of ten", -3.044522437723423),+                                    ("compose by multiplication", -3.4499875458315876)],+                               n = 55}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -1.006804739414987, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3677247801253174),+                                    ("intersect 2 numbers", -2.5649493574615367),+                                    ("integer (21..99) - TYPE 2", -2.5649493574615367)],+                               n = 19},+                   koData =+                     ClassData{prior = -0.4547361571149472, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.5533852381847867),+                                    ("intersect 2 numbers", -2.3025850929940455),+                                    ("integer - TYPE 1", -2.0794415416798357),+                                    ("fraction", -2.995732273553991),+                                    ("integer - TYPE 1: powers of ten", -2.5902671654458267),+                                    ("compose by multiplication", -2.995732273553991)],+                               n = 33}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -1.5955488002734333,+                               unseen = -4.5217885770490405,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.7191000372887952),+                                    ("integer - TYPE 1year (grain)", -3.41224721784874),+                                    ("integer (numeric)day (grain)", -2.5649493574615367),+                                    ("second", -3.817712325956905),+                                    ("integer - TYPE 1minute (grain)", -2.9014215940827497),+                                    ("integer (1..4) - for ordinalshour (grain)",+                                     -3.41224721784874),+                                    ("integer (numeric)second (grain)", -3.817712325956905),+                                    ("integer (numeric)year (grain)", -3.41224721784874),+                                    ("day", -2.5649493574615367), ("year", -2.9014215940827497),+                                    ("integer (numeric)week (grain)", -2.7191000372887952),+                                    ("hour", -2.3136349291806306),+                                    ("integer (numeric)minute (grain)", -3.817712325956905),+                                    ("few \47751hour (grain)", -2.9014215940827497),+                                    ("minute", -2.7191000372887952),+                                    ("integer (numeric)hour (grain)", -3.41224721784874)],+                               n = 29},+                   koData =+                     ClassData{prior = -0.22664618186541183,+                               unseen = -5.568344503761097,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.955082494888593),+                                    ("integer - TYPE 1quarter (grain)", -4.871373226762748),+                                    ("integer - TYPE 1day (grain)", -4.178226046202803),+                                    ("integer - TYPE 1year (grain)", -4.465908118654584),+                                    ("integer (numeric)day (grain)", -2.4290261913935436),+                                    ("intersect 2 numbersyear (grain)", -4.465908118654584),+                                    ("integer (numeric)quarter (grain)", -4.871373226762748),+                                    ("compose by multiplicationminute (grain)", -4.871373226762748),+                                    ("second", -3.7727609380946383),+                                    ("integer - TYPE 1minute (grain)", -3.7727609380946383),+                                    ("integer (1..4) - for ordinalsmonth (grain)",+                                     -4.465908118654584),+                                    ("integer (1..4) - for ordinalshour (grain)",+                                     -2.7313070632664775),+                                    ("integer (numeric)second (grain)", -4.871373226762748),+                                    ("integer (numeric)year (grain)", -2.6741486494265287),+                                    ("integer (21..99) - TYPE 2hour (grain)", -4.871373226762748),+                                    ("integer - TYPE 1week (grain)", -4.465908118654584),+                                    ("day", -2.3064238693012116), ("quarter", -4.465908118654584),+                                    ("year", -2.4290261913935436),+                                    ("integer (21..99) - TYPE 2minute (grain)", -4.178226046202803),+                                    ("integer (numeric)week (grain)", -4.465908118654584),+                                    ("integer (1..10) - TYPE 2hour (grain)", -4.871373226762748),+                                    ("hour", -1.900958761193047), ("month", -3.955082494888593),+                                    ("integer - TYPE 1second (grain)", -4.465908118654584),+                                    ("integer (numeric)minute (grain)", -3.955082494888593),+                                    ("integer (numeric)month (grain)", -4.465908118654584),+                                    ("integer (21..99) - TYPE 2year (grain)", -4.871373226762748),+                                    ("minute", -2.856470206220483),+                                    ("integer - TYPE 1: powers of tenminute (grain)",+                                     -4.871373226762748),+                                    ("integer (numeric)hour (grain)", -2.5199979695992702),+                                    ("integer (21..99) - TYPE 2second (grain)",+                                     -4.465908118654584)],+                               n = 114}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.3746934494414107, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.6486586255873816),+                                    ("hh:mm", -1.1786549963416462), ("hour", -1.6486586255873816),+                                    ("minute", -1.1786549963416462)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.1631508098056809, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.8472978603872037),+                                    ("hour", -0.8472978603872037)],+                               n = 5}}),+       ("a day - \54616\47336",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("am|pm <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.23262229526875347,+                               unseen = -4.543294782270004,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.824549292051046),+                                    ("<date>\50640", -3.146305132033365),+                                    ("time-of-day", -1.536867219599265),+                                    ("hour", -0.8437200390393196),+                                    ("<time-of-day>\51060\51204", -3.4339872044851463),+                                    ("<hour-of-day> half (as relative minutes)",+                                     -3.8394523125933104),+                                    ("minute", -3.146305132033365),+                                    ("after <time-of-day>", -3.8394523125933104),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -3.4339872044851463)],+                               n = 42},+                   koData =+                     ClassData{prior = -1.5723966407537513,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.2367626271489267),+                                    ("time-of-day", -2.0476928433652555),+                                    ("hour", -0.9490805546971459)],+                               n = 11}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -4.445176257083381e-2,+                               unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -3.1354942159291497,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("integer - TYPE 1: powers of ten",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("day with korean number - \51068\51068..\44396\51068",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("Hangul Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> (hour-of-day) relative minutes \51204",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.916290731874155),+                                    ("time-of-dayinteger (21..99) - TYPE 2", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer - TYPE 1", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8971199848858813), ("day", -1.6094379124341003),+                                    ("year", -1.8971199848858813),+                                    ("<integer> <unit-of-duration>", -0.916290731874155)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.0116009116784799, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -1.0296194171811581),+                                    ("hour", -1.540445040947149), ("minute", -1.540445040947149)],+                               n = 4}}),+       ("Constitution Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -2.833213344056216, unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -2.03688192726104), ("hour", -2.03688192726104),+                                    ("week-end", -2.03688192726104),+                                    ("day-of-week", -2.03688192726104)],+                               n = 4},+                   koData =+                     ClassData{prior = -6.0624621816434854e-2,+                               unseen = -4.969813299576001,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -3.8642323415917974),+                                    ("year (latent)", -1.967112356705916),+                                    ("second", -3.8642323415917974),+                                    ("time-of-day (latent)", -1.9183221925364844),+                                    ("year", -1.967112356705916),+                                    ("<duration> ago", -3.8642323415917974),+                                    ("time-of-day", -2.477937980471907),+                                    ("hour", -1.1786549963416462), ("seconds", -3.8642323415917974),+                                    ("<datetime> - <datetime> (interval)", -3.8642323415917974),+                                    ("<time-of-day>\51060\51204", -3.8642323415917974),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -3.353406717825807)],+                               n = 64}}),+       ("<date>\50640",+        Classifier{okData =+                     ClassData{prior = -7.410797215372185e-2,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.824549292051046), ("day", -2.3353749158170367),+                                    ("am|pm <time-of-day>", -2.0476928433652555),+                                    ("<duration> ago", -2.740840023925201),+                                    ("time-of-day", -2.0476928433652555),+                                    ("hour", -1.0360919316867756), ("month", -2.740840023925201)],+                               n = 13},+                   koData =+                     ClassData{prior = -2.639057329615259, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.5040773967762742),+                                    ("hour", -1.5040773967762742)],+                               n = 1}}),+       ("integer (1..10) - TYPE 2",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day",+        Classifier{okData =+                     ClassData{prior = -0.5328045304847658,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.5753641449035618),+                                    ("integer (1..4) - for ordinals", -1.1631508098056809),+                                    ("integer (1..10) - TYPE 2", -2.772588722239781)],+                               n = 27},+                   koData =+                     ClassData{prior = -0.8842024173226546,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.3862943611198906),+                                    ("integer (21..99) - TYPE 2", -2.4849066497880004),+                                    ("integer (1..4) - for ordinals", -0.8754687373538999),+                                    ("few \47751", -1.5686159179138452)],+                               n = 19}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList [("integer (1..4) - for ordinals", 0.0)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.5040773967762742),+                                    ("<integer> <unit-of-duration>", -0.8109302162163288),+                                    ("hour", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("month",+        Classifier{okData =+                     ClassData{prior = -5.5569851154810765e-2,+                               unseen = -3.6375861597263857,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -5.5569851154810765e-2),+                                    ("integer - TYPE 1", -2.917770732084279)],+                               n = 35},+                   koData =+                     ClassData{prior = -2.917770732084279, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList [("integer - TYPE 1", -0.2876820724517809)],+                               n = 2}}),+       ("midnight|EOD|end of day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.3862943611198906), ("month", -1.3862943611198906),+                                    ("day-of-week", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day", -1.252762968495368),+                                    ("hour", -1.252762968495368)],+                               n = 1}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.2992829841302609),+                                    ("month (grain)", -2.3978952727983707),+                                    ("year (grain)", -2.3978952727983707),+                                    ("week (grain)", -1.2992829841302609),+                                    ("year", -2.3978952727983707), ("month", -2.3978952727983707)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.0116009116784799, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("week (grain)", -1.6739764335716716),+                                    ("day", -1.6739764335716716),+                                    ("day (grain)", -1.6739764335716716)],+                               n = 4}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.367123614131617),+                                    ("integer - TYPE 1year (grain)", -2.772588722239781),+                                    ("integer - TYPE 1minute (grain)", -2.772588722239781),+                                    ("integer (1..4) - for ordinalsmonth (grain)",+                                     -2.772588722239781),+                                    ("integer (numeric)year (grain)", -2.772588722239781),+                                    ("integer - TYPE 1week (grain)", -2.772588722239781),+                                    ("year", -2.367123614131617),+                                    ("integer (numeric)week (grain)", -2.772588722239781),+                                    ("hour", -2.772588722239781), ("month", -2.367123614131617),+                                    ("integer (numeric)minute (grain)", -2.772588722239781),+                                    ("integer (numeric)month (grain)", -2.772588722239781),+                                    ("minute", -2.367123614131617),+                                    ("integer (numeric)hour (grain)", -2.772588722239781)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("seconds",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.916290731874155),+                                    ("integer (21..99) - TYPE 2", -0.916290731874155)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.252762968495368),+                                    ("integer - TYPE 1", -0.8472978603872037),+                                    ("integer (21..99) - TYPE 2", -1.252762968495368)],+                               n = 4}}),+       ("<time> \47560\51648\47561 <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.540445040947149),+                                    ("monthday (grain)", -1.9459101490553135),+                                    ("monthweek", -1.540445040947149),+                                    ("intersectweek (grain)", -1.9459101490553135),+                                    ("intersectday (grain)", -1.9459101490553135),+                                    ("monthweek (grain)", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.2039728043259361),+                                    ("monthday (grain)", -1.6094379124341003),+                                    ("intersectday (grain)", -1.6094379124341003)],+                               n = 2}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = -0.17589066646366416,+                               unseen = -4.1588830833596715,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.044522437723423), ("second", -3.4499875458315876),+                                    ("day", -2.5336968139574325), ("year", -3.044522437723423),+                                    ("<integer> <unit-of-duration>", -1.1986957472250923),+                                    ("a day - \54616\47336", -3.044522437723423),+                                    ("<integer> and an half hours", -2.3513752571634776),+                                    ("hour", -2.1972245773362196), ("minute", -1.6582280766035324),+                                    ("about <duration>", -3.4499875458315876)],+                               n = 26},+                   koData =+                     ClassData{prior = -1.824549292051046, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -1.252762968495368),+                                    ("minute", -1.252762968495368)],+                               n = 5}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.46262352194811296,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersecthh:mm", -2.7300291078209855),+                                    ("intersectam|pm <time-of-day>", -2.7300291078209855),+                                    ("minuteminute", -1.749199854809259),+                                    ("hh:mmhh:mm", -2.03688192726104),+                                    ("dayday", -1.8827312474337816),+                                    ("hourhour", -2.2192034840549946),+                                    ("intersectday", -2.7300291078209855),+                                    ("am|pm <time-of-day>am|pm <time-of-day>", -2.7300291078209855),+                                    ("intersectintersect", -2.7300291078209855)],+                               n = 17},+                   koData =+                     ClassData{prior = -0.9932517730102834,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.8562979903656263),+                                    ("time-of-dayam|pm <time-of-day>", -2.367123614131617),+                                    ("intersectmonth", -2.367123614131617),+                                    ("dayday", -2.367123614131617),+                                    ("hourhour", -1.8562979903656263),+                                    ("last <time>am|pm <time-of-day>", -2.367123614131617),+                                    ("dayintersect", -2.367123614131617)],+                               n = 10}}),+       ("<time-of-day>\51060\51204",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("am|pm <time-of-day>", -1.540445040947149),+                                    ("time-of-day", -1.540445040947149),+                                    ("hour", -1.0296194171811581)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.791759469228055),+                                    ("hour", -1.791759469228055), ("minute", -1.3862943611198906),+                                    ("<hour-of-day> <integer> (as relative minutes)",+                                     -1.3862943611198906)],+                               n = 3}}),+       ("New Year's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<1..4> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer - TYPE 1quarter (grain)", -0.916290731874155),+                                    ("quarter", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)quarter (grain)", -0.916290731874155),+                                    ("quarter", -0.916290731874155)],+                               n = 1}}),+       ("Children's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.9444616088408514, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.4271163556401458),+                                    ("hh:mmhh:mm", -1.4271163556401458),+                                    ("hourhour", -2.120263536200091),+                                    ("am|pm <time-of-day>am|pm <time-of-day>", -2.120263536200091)],+                               n = 7},+                   koData =+                     ClassData{prior = -0.49247648509779407,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-dayam|pm <time-of-day>", -2.3978952727983707),+                                    ("time-of-daytime-of-day (latent)", -2.803360380906535),+                                    ("hh:mmtime-of-day (latent)", -1.7047480922384253),+                                    ("am|pm <time-of-day>time-of-day (latent)", -2.803360380906535),+                                    ("am|pm <time-of-day><time-of-day>\51060\51204",+                                     -2.803360380906535),+                                    ("hourhour", -1.550597412411167),+                                    ("time-of-day<time-of-day>\51060\51204", -2.803360380906535),+                                    ("minutehour", -1.7047480922384253)],+                               n = 11}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.5902671654458267), ("second", -2.5902671654458267),+                                    ("integer - TYPE 1minute (grain)", -2.995732273553991),+                                    ("integer (1..4) - for ordinalsmonth (grain)",+                                     -2.995732273553991),+                                    ("integer (1..4) - for ordinalshour (grain)",+                                     -2.995732273553991),+                                    ("integer (numeric)second (grain)", -2.995732273553991),+                                    ("integer (21..99) - TYPE 2hour (grain)", -2.995732273553991),+                                    ("integer - TYPE 1week (grain)", -2.995732273553991),+                                    ("integer (numeric)week (grain)", -2.995732273553991),+                                    ("hour", -2.0794415416798357), ("month", -2.5902671654458267),+                                    ("integer - TYPE 1second (grain)", -2.995732273553991),+                                    ("integer (numeric)minute (grain)", -2.995732273553991),+                                    ("integer (numeric)month (grain)", -2.995732273553991),+                                    ("minute", -2.5902671654458267),+                                    ("integer (numeric)hour (grain)", -2.5902671654458267)],+                               n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> half (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.5040773967762742, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("lunch", -1.8718021769015913),+                                    ("time-of-day (latent)", -1.8718021769015913),+                                    ("am|pm <time-of-day>", -1.8718021769015913),+                                    ("time-of-day", -1.8718021769015913),+                                    ("hour", -0.9555114450274363)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.25131442828090605,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.7884573603642702),+                                    ("hour", -0.7884573603642702)],+                               n = 14}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = -1.1727202608218315, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -0.37037378829689427,+                               unseen = -3.4339872044851463,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 29}}),+       ("compose by multiplication",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer - TYPE 1integer - TYPE 1: powers of ten", 0.0)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> and an half hours", -1.0986122886681098),+                                    ("minute", -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -1.0986122886681098),+                                    ("hour", -1.0986122886681098)],+                               n = 1}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-daycompose by multiplication", -1.8718021769015913),+                                    ("time-of-dayinteger (numeric)", -1.8718021769015913),+                                    ("hour", -1.1786549963416462),+                                    ("time-of-dayinteger (21..99) - TYPE 2", -1.8718021769015913)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (21..99) - TYPE 2",+                                     -2.2512917986064953),+                                    ("time-of-day (latent)integer - TYPE 1", -1.55814461804655),+                                    ("time-of-day (latent)integer - TYPE 1: powers of ten",+                                     -2.2512917986064953),+                                    ("hour", -0.9985288301111273),+                                    ("time-of-dayinteger (21..99) - TYPE 2", -2.2512917986064953)],+                               n = 6}}),+       ("few \47751",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -1.466337068793427), ("day", -1.466337068793427),+                                    ("hour", -1.466337068793427), ("morning", -1.8718021769015913),+                                    ("week-end", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day-of-week",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.713572066704308,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 39},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/MY.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.MY (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/NB.hs view
@@ -0,0 +1,1603 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.NB (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.4350845252893227),+                                    ("<time-of-day> o'clock", -2.3513752571634776),+                                    ("hh:mm", -1.6582280766035324), ("hour", -1.6582280766035324),+                                    ("minute", -1.252762968495368)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.7546493803177391, unseen = -4.912654885736052,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 134},+                   koData =+                     ClassData{prior = -0.6352093434537263, unseen = -5.030437921392435,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 151}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Father's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.0986122886681098),+                                    ("tomorrowevening", -2.0149030205422647),+                                    ("named-daymorning", -2.0149030205422647),+                                    ("tomorrowlunch", -2.0149030205422647),+                                    ("yesterdayevening", -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -1.1786549963416462),+                                    ("year (latent)in|during the <part-of-day>",+                                     -1.1786549963416462)],+                               n = 3}}),+       ("dd/mm",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2657031657330056, unseen = -4.605170185988091,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> timezone", -3.4965075614664802),+                                    ("time-of-day (latent)", -1.2278240201481159),+                                    ("relative minutes after|past <integer> (hour-of-day)",+                                     -3.4965075614664802),+                                    ("hh:mm", -2.030170492673053),+                                    ("<time-of-day> sharp", -3.4965075614664802),+                                    ("hour", -1.1611326456494435), ("minute", -1.7619065060783738)],+                               n = 46},+                   koData =+                     ClassData{prior = -1.455287232606842, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.8472978603872037),+                                    ("hour", -0.8472978603872037)],+                               n = 14}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = -0.3313571359544425, unseen = -4.189654742026425,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -3.481240089335692),+                                    ("the <day-of-month> (non ordinal)", -3.0757749812275272),+                                    ("<day-of-month>(ordinal) <named-month>", -2.228477120840324),+                                    ("day", -0.807091439909163),+                                    ("the <day-of-month> (ordinal)", -3.481240089335692),+                                    ("named-day", -1.8718021769015913),+                                    ("<day-of-month> (ordinal)", -1.8718021769015913)],+                               n = 28},+                   koData =+                     ClassData{prior = -1.2656663733312759,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -2.3353749158170367),+                                    ("time-of-day (latent)", -1.1314021114911006),+                                    ("hour", -0.9490805546971459)],+                               n = 11}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.9808292530117262),+                                    ("hh:mmhh:mm", -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 2}}),+       ("between <datetime> and <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("hh:mmhh:mm", -1.0986122886681098)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.2992829841302609),+                                    ("minuteminute", -1.7047480922384253),+                                    ("minutehour", -1.2992829841302609),+                                    ("hh:mmintersect", -1.7047480922384253)],+                               n = 3}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> more <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)minute (grain)", -1.252762968495368),+                                    ("integer (0..19)minute (grain)", -1.252762968495368),+                                    ("minute", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.10536051565782628,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -2.3025850929940455,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037),+                                    ("ordinals (first..31st)quarter (grain)", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037),+                                    ("ordinals (first..31st)quarter (grain)", -1.252762968495368)],+                               n = 2}}),+       ("Last year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.4392032477400145, unseen = -5.860786223465865,+                               likelihoods =+                                 HashMap.fromList+                                   [("<datetime> - <datetime> (interval)on <date>",+                                     -4.0661736852554045),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.0661736852554045),+                                    ("hourday", -5.1647859739235145),+                                    ("dayhour", -2.9134941753170187),+                                    ("daymonth", -2.9134941753170187),+                                    ("monthyear", -3.0853444322436783),+                                    ("intersecthh:mm", -5.1647859739235145),+                                    ("the <day-of-month> (ordinal)named-month", -3.912023005428146),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -4.75932086581535),+                                    ("last <day-of-week> of <time>year", -4.75932086581535),+                                    ("todayat <time-of-day>", -4.75932086581535),+                                    ("dayday", -3.0247198104272432),+                                    ("dd/mmat <time-of-day>", -4.248495242049359),+                                    ("intersect by \",\"hh:mm", -4.248495242049359),+                                    ("intersectnamed-month", -4.75932086581535),+                                    ("dayyear", -3.2929837970219227),+                                    ("named-daythis <time>", -4.0661736852554045),+                                    ("tomorrow<time-of-day> sharp", -4.75932086581535),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -4.75932086581535),+                                    ("named-day<time> timezone", -4.471638793363569),+                                    ("named-monthyear", -3.0853444322436783),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.0661736852554045),+                                    ("on <date>named-month", -3.912023005428146),+                                    ("tomorrowuntil <time-of-day>", -4.75932086581535),+                                    ("absorption of , after named day<day-of-month> (non ordinal) <named-month>",+                                     -4.471638793363569),+                                    ("after <time-of-day>at <time-of-day>", -4.75932086581535),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -4.75932086581535),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -5.1647859739235145),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -5.1647859739235145),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.75932086581535),+                                    ("named-daynext <cycle>", -5.1647859739235145),+                                    ("named-dayintersect", -4.75932086581535),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.75932086581535),+                                    ("tomorrowafter <time-of-day>", -4.75932086581535),+                                    ("from <time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.248495242049359),+                                    ("dayminute", -2.8134107167600364),+                                    ("from <datetime> - <datetime> (interval)on <date>",+                                     -4.471638793363569),+                                    ("<ordinal> <cycle> of <time>year", -4.75932086581535),+                                    ("minuteday", -2.5620962884791303),+                                    ("absorption of , after named dayintersect",+                                     -5.1647859739235145),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -5.1647859739235145),+                                    ("named-dayon <date>", -4.75932086581535),+                                    ("named-dayat <time-of-day>", -4.75932086581535),+                                    ("yearhh:mm", -5.1647859739235145),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -5.1647859739235145),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -4.75932086581535),+                                    ("dd/mmyear", -4.75932086581535),+                                    ("at <time-of-day>on <date>", -5.1647859739235145),+                                    ("between <time-of-day> and <time-of-day> (interval)on <date>",+                                     -5.1647859739235145),+                                    ("between <datetime> and <datetime> (interval)on <date>",+                                     -5.1647859739235145),+                                    ("dayweek", -4.0661736852554045),+                                    ("weekyear", -4.248495242049359),+                                    ("hh:mmtomorrow", -4.471638793363569),+                                    ("tomorrowat <time-of-day>", -3.912023005428146),+                                    ("named-daythis <cycle>", -4.471638793363569),+                                    ("named-daythe <day-of-month> (ordinal)", -5.1647859739235145),+                                    ("at <time-of-day>tomorrow", -4.75932086581535),+                                    ("last <cycle> of <time>year", -4.248495242049359),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -4.75932086581535),+                                    ("yearminute", -5.1647859739235145)],+                               n = 136},+                   koData =+                     ClassData{prior = -1.034370019939756, unseen = -5.43372200355424,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -4.736198448394496),+                                    ("dayhour", -3.2321210516182215),+                                    ("daymonth", -2.133508762950112),+                                    ("monthday", -3.8199077165203406),+                                    ("monthyear", -3.8199077165203406),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -3.4834354798991276),+                                    ("named-dayhh:mm", -4.736198448394496),+                                    ("dd/mmat <time-of-day>", -3.8199077165203406),+                                    ("hourhour", -3.4834354798991276),+                                    ("dayyear", -3.4834354798991276),+                                    ("named-daythis <time>", -2.596132284898225),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -4.330733340286331),+                                    ("minutemonth", -4.330733340286331),+                                    ("named-monthyear", -3.8199077165203406),+                                    ("in|during the <part-of-day>until <time-of-day>",+                                     -4.330733340286331),+                                    ("absorption of , after named daynamed-month",+                                     -3.6375861597263857),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.736198448394496),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -4.330733340286331),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.736198448394496),+                                    ("until <time-of-day>on <date>", -4.736198448394496),+                                    ("dayminute", -3.349904087274605),+                                    ("minuteday", -3.2321210516182215),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -4.736198448394496),+                                    ("named-dayon <date>", -4.736198448394496),+                                    ("named-dayat <time-of-day>", -3.8199077165203406),+                                    ("hh:mmon <date>", -3.349904087274605),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -4.736198448394496),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -3.8199077165203406),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -3.8199077165203406),+                                    ("this <part-of-day>until <time-of-day>", -4.330733340286331),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -4.330733340286331),+                                    ("tomorrownoon", -4.736198448394496),+                                    ("this <time>until <time-of-day>", -4.330733340286331),+                                    ("minuteyear", -4.330733340286331),+                                    ("yearminute", -4.330733340286331)],+                               n = 75}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)intersect",+                                     -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)named-month",+                                     -1.7346010553881064),+                                    ("weekmonth", -1.2237754316221157),+                                    ("ordinals (first..31st)day (grain)named-month",+                                     -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8754687373538999, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.2237754316221157),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.1400661634962708),+                                    ("hh:mmhh:mm", -1.2237754316221157),+                                    ("hourhour", -2.1400661634962708)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.5389965007326869,+                               unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -1.4350845252893227),+                                    ("minuteminute", -1.6582280766035324),+                                    ("minutehour", -1.4350845252893227),+                                    ("hh:mmintersect", -1.6582280766035324)],+                               n = 7}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("month (grain)", -2.3025850929940455),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.6094379124341003),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("month", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.1972245773362196),+                                    ("hh:mmhh:mm", -1.0986122886681098),+                                    ("hourhour", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 5}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 3}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)quarter (grain)year",+                                     -1.252762968495368),+                                    ("quarteryear", -0.8472978603872037),+                                    ("ordinal (digits)quarter (grain)year", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <cycle> after <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (grain)christmas eve", -0.6931471805599453),+                                    ("yearday", -0.6931471805599453)],+                               n = 2}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a pair",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7472144018302211),+                                    ("ordinals (first..31st)named-dayintersect",+                                     -0.9985288301111273),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -1.845826690498331)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7621400520468967),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -0.7621400520468967)],+                               n = 6}}),+       ("the <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (first..31st)",+        Classifier{okData =+                     ClassData{prior = -5.129329438755058e-2,+                               unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -2.995732273553991, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.189654742026425,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 64},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.367295829986474,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 27},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8472978603872037), ("evening", -1.252762968495368),+                                    ("morning", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7308875085427924),+                                    ("morning", -0.7308875085427924)],+                               n = 12}}),+       ("christmas eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -9.53101798043249e-2,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.749199854809259),+                                    ("ordinal (digits)named-month", -1.0560526742493137),+                                    ("month", -0.7375989431307791)],+                               n = 10},+                   koData =+                     ClassData{prior = -2.3978952727983707, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -0.916290731874155),+                                    ("month", -0.916290731874155)],+                               n = 1}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 23}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -1.3862943611198906),+                                    ("hour", -0.9808292530117262),+                                    ("evening", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7672551527136672),+                                    ("morning", -0.7672551527136672)],+                               n = 12}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> after <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (grain)christmas eve", -0.6931471805599453),+                                    ("yearday", -0.6931471805599453)],+                               n = 2}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("the <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)", -1.0116009116784799),+                                    ("ordinal (digits)", -0.45198512374305727)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> from now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("second", -1.4469189829363254), ("year", -2.1400661634962708),+                                    ("<integer> <unit-of-duration>", -1.2237754316221157),+                                    ("a <unit-of-duration>", -1.7346010553881064),+                                    ("minute", -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5686159179138452),+                                    ("year (grain)", -2.0794415416798357),+                                    ("week (grain)", -1.5686159179138452),+                                    ("day", -2.4849066497880004), ("quarter", -2.4849066497880004),+                                    ("year", -2.0794415416798357),+                                    ("quarter (grain)", -2.4849066497880004),+                                    ("day (grain)", -2.4849066497880004)],+                               n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.6094379124341003),+                                    ("day (grain)", -1.6094379124341003)],+                               n = 1}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.5596157879354228,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.3862943611198906),+                                    ("hour", -1.3862943611198906),+                                    ("<hour-of-day> half (as relative minutes)",+                                     -1.3862943611198906),+                                    ("minute", -1.3862943611198906)],+                               n = 4}}),+       ("christmas days",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.99714282850325, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)", -2.5317807984289897e-2)],+                               n = 38},+                   koData =+                     ClassData{prior = -0.46034171833399856,+                               unseen = -4.219507705176107,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.27286698666664033),+                                    ("integer (0..19)", -1.4321038971511848)],+                               n = 65}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.1431008436406733, unseen = -3.332204510175204,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 26},+                   koData =+                     ClassData{prior = -2.0149030205422647, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.7621400520468967),+                                    ("named-dayintersect", -1.6094379124341003)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.579818495252942, unseen = -4.672828834461907,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.466214516775848),+                                    ("integer (0..19)year (grain)", -3.5648268054439574),+                                    ("integer (numeric)day (grain)", -2.871679624884012),+                                    ("integer (0..19)hour (grain)", -3.970291913552122),+                                    ("second", -3.2771447329921766),+                                    ("integer (numeric)second (grain)", -3.970291913552122),+                                    ("a pairhour (grain)", -3.970291913552122),+                                    ("integer (numeric)year (grain)", -3.5648268054439574),+                                    ("day", -2.2655438213136967), ("year", -3.054001181677967),+                                    ("integer (numeric)week (grain)", -3.2771447329921766),+                                    ("integer (0..19)month (grain)", -3.970291913552122),+                                    ("integer (0..19)second (grain)", -3.5648268054439574),+                                    ("hour", -2.871679624884012), ("month", -3.5648268054439574),+                                    ("integer (numeric)minute (grain)", -2.717528945056754),+                                    ("integer (0..19)minute (grain)", -3.054001181677967),+                                    ("integer (numeric)month (grain)", -3.970291913552122),+                                    ("minute", -2.2655438213136967),+                                    ("integer (numeric)hour (grain)", -3.2771447329921766),+                                    ("integer (0..19)day (grain)", -2.871679624884012),+                                    ("integer (0..19)week (grain)", -2.871679624884012)],+                               n = 42},+                   koData =+                     ClassData{prior = -0.8209805520698302, unseen = -4.48863636973214,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6855773452501515),+                                    ("integer (0..19)year (grain)", -3.378724525810097),+                                    ("integer (numeric)day (grain)", -3.0910424533583156),+                                    ("integer (0..19)hour (grain)", -3.784189633918261),+                                    ("second", -2.867898902044106),+                                    ("integer (numeric)second (grain)", -3.378724525810097),+                                    ("integer (numeric)year (grain)", -3.0910424533583156),+                                    ("day", -2.6855773452501515), ("year", -2.6855773452501515),+                                    ("integer (numeric)week (grain)", -3.378724525810097),+                                    ("integer (0..19)month (grain)", -3.0910424533583156),+                                    ("integer (0..19)second (grain)", -3.378724525810097),+                                    ("hour", -2.6855773452501515), ("month", -2.6855773452501515),+                                    ("integer (numeric)minute (grain)", -3.378724525810097),+                                    ("integer (0..19)minute (grain)", -3.378724525810097),+                                    ("integer (numeric)month (grain)", -3.378724525810097),+                                    ("minute", -2.867898902044106),+                                    ("integer (numeric)hour (grain)", -2.867898902044106),+                                    ("integer (0..19)day (grain)", -3.378724525810097),+                                    ("integer (0..19)week (grain)", -3.0910424533583156)],+                               n = 33}}),+       ("<duration> after <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("a <unit-of-duration>christmas eve", -1.0986122886681098),+                                    ("yearday", -0.8109302162163288),+                                    ("<integer> <unit-of-duration>christmas eve",+                                     -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("integer (numeric)time-of-day (latent)", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.367123614131617),+                                    ("year (grain)", -2.367123614131617),+                                    ("second", -1.8562979903656263),+                                    ("week (grain)", -2.367123614131617),+                                    ("day", -2.772588722239781),+                                    ("minute (grain)", -2.367123614131617),+                                    ("year", -2.367123614131617),+                                    ("second (grain)", -1.8562979903656263),+                                    ("minute", -2.367123614131617),+                                    ("day (grain)", -2.772588722239781)],+                               n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.1590646946296874, unseen = -4.442651256490317,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>named-day", -3.7376696182833684),+                                    ("intersect by \",\"year", -3.7376696182833684),+                                    ("hh:mmintersect by \",\"", -3.7376696182833684),+                                    ("dayday", -2.032921526044943),+                                    ("hh:mmnamed-day", -3.7376696182833684),+                                    ("named-dayintersect by \",\"", -3.332204510175204),+                                    ("dayyear", -2.8213788864092133),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -3.7376696182833684),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -3.332204510175204),+                                    ("<named-month> <day-of-month> (non ordinal)named-day",+                                     -3.7376696182833684),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -3.044522437723423),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.639057329615259),+                                    ("hh:mmintersect", -3.7376696182833684),+                                    ("intersect by \",\"intersect", -3.7376696182833684),+                                    ("named-dayintersect", -3.7376696182833684),+                                    ("at <time-of-day>intersect", -3.7376696182833684),+                                    ("dayminute", -2.639057329615259),+                                    ("intersectyear", -3.7376696182833684),+                                    ("minuteday", -2.032921526044943),+                                    ("hh:mmabsorption of , after named day", -3.7376696182833684),+                                    ("at <time-of-day>intersect by \",\"", -3.7376696182833684),+                                    ("at <time-of-day>absorption of , after named day",+                                     -3.7376696182833684),+                                    ("intersectintersect", -3.7376696182833684),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.332204510175204)],+                               n = 29},+                   koData =+                     ClassData{prior = -1.916922612182061, unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.791759469228055),+                                    ("daymonth", -1.791759469228055)],+                               n = 5}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -2.197890671877523e-2,+                               unseen = -3.8501476017100584,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 45},+                   koData =+                     ClassData{prior = -3.828641396489095, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.290459441148391,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 71},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> sharp",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.2992829841302609),+                                    ("time-of-day (latent)", -1.2992829841302609),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = -1.0116009116784799,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.4816045409242156),+                                    ("daymonth", -1.1451323043030026),+                                    ("named-daylast <cycle>", -2.3978952727983707),+                                    ("named-daynext <cycle>", -2.3978952727983707),+                                    ("named-dayintersect", -1.9924301646902063),+                                    ("dayweek", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.329135947279942),+                                    ("daymonth", -0.8183103235139514),+                                    ("named-dayintersect", -1.580450375560848)],+                               n = 14}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.580450375560848), ("day", -1.916922612182061),+                                    ("year", -2.4277482359480516),+                                    ("<integer> <unit-of-duration>", -0.8873031950009028),+                                    ("a <unit-of-duration>", -2.833213344056216),+                                    ("month", -2.4277482359480516)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -1.6739764335716716,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.2809338454620642),+                                    ("named-day", -1.2809338454620642),+                                    ("hour", -1.791759469228055), ("week-end", -1.791759469228055)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.2076393647782445, unseen = -4.07753744390572,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.8632184332102),+                                    ("time-of-day (latent)", -1.1160040313799788),+                                    ("named-day", -2.451005098112319),+                                    ("intersect by \"of\", \"from\", \"'s\"", -2.451005098112319),+                                    ("hour", -1.1160040313799788)],+                               n = 26}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)", -1.0116009116784799),+                                    ("ordinal (digits)", -0.45198512374305727)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -0.8873031950009028),+                                    ("hour", -0.8873031950009028)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.5040773967762742),+                                    ("hh:mm", -1.5040773967762742),+                                    ("minute", -1.0986122886681098)],+                               n = 2}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.6931471805599453),+                                    ("integer (0..19)", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("decimal number",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.7047480922384253),+                                    ("month (grain)", -1.9924301646902063),+                                    ("year (grain)", -1.9924301646902063),+                                    ("week (grain)", -1.7047480922384253),+                                    ("year", -1.9924301646902063), ("month", -1.9924301646902063)],+                               n = 7},+                   koData =+                     ClassData{prior = -1.0116009116784799, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("week (grain)", -1.6739764335716716),+                                    ("day", -1.6739764335716716),+                                    ("day (grain)", -1.6739764335716716)],+                               n = 4}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.793208009442517),+                                    ("integer (0..19)year (grain)", -3.1986731175506815),+                                    ("integer (numeric)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)hour (grain)", -3.1986731175506815),+                                    ("second", -2.793208009442517),+                                    ("integer (numeric)second (grain)", -3.1986731175506815),+                                    ("integer (numeric)year (grain)", -3.1986731175506815),+                                    ("day", -2.793208009442517), ("year", -2.793208009442517),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("integer (0..19)month (grain)", -3.1986731175506815),+                                    ("integer (0..19)second (grain)", -3.1986731175506815),+                                    ("hour", -2.793208009442517), ("month", -2.793208009442517),+                                    ("integer (numeric)minute (grain)", -3.1986731175506815),+                                    ("integer (0..19)minute (grain)", -3.1986731175506815),+                                    ("integer (numeric)month (grain)", -3.1986731175506815),+                                    ("minute", -2.793208009442517),+                                    ("integer (numeric)hour (grain)", -3.1986731175506815),+                                    ("integer (0..19)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)week (grain)", -3.1986731175506815)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.418840607796598,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.0204248861443626),+                                    ("<integer> more <unit-of-duration>", -3.3081069585961433),+                                    ("number.number hours", -3.713572066704308),+                                    ("second", -2.797281334830153), ("day", -2.6149597780361984),+                                    ("half an hour", -3.713572066704308),+                                    ("<integer> <unit-of-duration>", -1.3156767939059373),+                                    ("a <unit-of-duration>", -2.46080909820894),+                                    ("<integer> and an half hours", -3.3081069585961433),+                                    ("hour", -2.6149597780361984), ("minute", -1.4622802680978126),+                                    ("about <duration>", -3.3081069585961433)],+                               n = 35},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8362480242006186,+                               unseen = -3.6888794541139363,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.466337068793427),+                                    ("hh:mmhh:mm", -1.466337068793427),+                                    ("dayday", -1.8718021769015913),+                                    ("<day-of-month> (non ordinal) <named-month><day-of-month> (non ordinal) <named-month>",+                                     -1.8718021769015913)],+                               n = 13},+                   koData =+                     ClassData{prior = -0.5679840376059393, unseen = -3.871201010907891,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -2.0583881324820035),+                                    ("minuteminute", -1.9042374526547454),+                                    ("hh:mmhh:mm", -3.1570004211501135),+                                    ("dayyear", -2.751535313041949),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -2.751535313041949),+                                    ("hh:mmintersect", -2.0583881324820035),+                                    ("dd/mmyear", -2.751535313041949),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -2.0583881324820035),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -2.751535313041949),+                                    ("minuteyear", -2.751535313041949),+                                    ("yearminute", -2.751535313041949)],+                               n = 17}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8109302162163288, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.7985076962177716),+                                    ("hh:mmhh:mm", -0.7985076962177716)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.587786664902119, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.8754687373538999),+                                    ("minuteminute", -2.4849066497880004),+                                    ("hh:mmhh:mm", -2.4849066497880004),+                                    ("minutehour", -0.8754687373538999)],+                               n = 10}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.04305126783455,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.639057329615259),+                                    ("integer (0..19)year (grain)", -3.332204510175204),+                                    ("integer (numeric)day (grain)", -2.9267394020670396),+                                    ("second", -2.9267394020670396),+                                    ("integer (numeric)second (grain)", -3.332204510175204),+                                    ("integer (numeric)year (grain)", -2.9267394020670396),+                                    ("day", -2.639057329615259), ("year", -2.639057329615259),+                                    ("integer (numeric)week (grain)", -3.332204510175204),+                                    ("integer (0..19)month (grain)", -2.9267394020670396),+                                    ("integer (0..19)second (grain)", -3.332204510175204),+                                    ("hour", -2.9267394020670396), ("month", -2.639057329615259),+                                    ("integer (numeric)minute (grain)", -3.332204510175204),+                                    ("integer (0..19)minute (grain)", -3.332204510175204),+                                    ("integer (numeric)month (grain)", -3.332204510175204),+                                    ("minute", -2.9267394020670396),+                                    ("integer (numeric)hour (grain)", -2.9267394020670396),+                                    ("integer (0..19)day (grain)", -3.332204510175204),+                                    ("integer (0..19)week (grain)", -2.9267394020670396)],+                               n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.4418327522790392, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 5}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 18},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3}}),+       ("<hour-of-day> half (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("about <time-of-day>", -1.7346010553881064),+                                    ("time-of-day (latent)", -1.041453874828161),+                                    ("hour", -0.7537718023763802)],+                               n = 7}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.4816045409242156),+                                    ("week (grain)named-month", -1.9924301646902063),+                                    ("day (grain)intersect", -1.9924301646902063),+                                    ("weekmonth", -1.4816045409242156),+                                    ("day (grain)named-month", -1.9924301646902063),+                                    ("week (grain)intersect", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.0986122886681098),+                                    ("ordinal (digits)named-month", -1.5040773967762742),+                                    ("month", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.7537718023763802, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.6863989535702288),+                                    ("intersect", -2.1972245773362196),+                                    ("tomorrow", -2.1972245773362196), ("day", -2.1972245773362196),+                                    ("hour", -1.349926716949016)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.6359887667199967,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("this <part-of-day>", -2.268683541318364),+                                    ("christmas eve", -2.268683541318364),+                                    ("in|during the <part-of-day>", -2.268683541318364),+                                    ("day", -2.268683541318364), ("hh:mm", -2.6741486494265287),+                                    ("hour", -1.4213856809311607), ("minute", -2.6741486494265287),+                                    ("this <time>", -2.268683541318364)],+                               n = 9}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = -4.8790164169432056e-2,+                               unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -3.044522437723423, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 9}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -1.2443240998495033,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.1354942159291497),+                                    ("intersect", -2.7300291078209855),+                                    ("season", -2.2192034840549946),+                                    ("next <cycle>", -3.1354942159291497),+                                    ("named-month", -2.7300291078209855),+                                    ("day", -1.8827312474337816),+                                    ("christmas days", -2.7300291078209855),+                                    ("hour", -1.8827312474337816), ("evening", -3.1354942159291497),+                                    ("month", -2.2192034840549946),+                                    ("morning", -3.1354942159291497),+                                    ("week-end", -2.2192034840549946)],+                               n = 17},+                   koData =+                     ClassData{prior = -0.3398678256223512, unseen = -4.574710978503383,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.9993988340062996),+                                    ("named-month", -1.6199092123013958),+                                    ("hour", -1.9993988340062996), ("month", -1.1303609869826898),+                                    ("morning", -1.9993988340062996)],+                               n = 42}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/NL.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.NL (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/PL.hs view
@@ -0,0 +1,2307 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.PL (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("five",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.5997731097824868, unseen = -4.875197323201151,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 129},+                   koData =+                     ClassData{prior = -0.7961464200320919, unseen = -4.68213122712422,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 106}}),+       ("exactly <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -1.3862943611198906),+                                    ("<integer> (latent time-of-day)", -1.791759469228055),+                                    ("hour", -0.8754687373538999),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> before <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.6931471805599453),+                                    ("day (grain)yesterday", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Father's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> <cycle> <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -2.120263536200091),+                                    ("quarteryear", -2.5257286443082556),+                                    ("third ordinalday (grain)on <date>", -2.5257286443082556),+                                    ("first ordinalweek (grain)named-month", -2.5257286443082556),+                                    ("weekmonth", -1.4271163556401458),+                                    ("ordinal (digits)quarter (grain)year", -2.5257286443082556),+                                    ("first ordinalweek (grain)intersect", -2.120263536200091),+                                    ("third ordinalday (grain)named-month", -2.5257286443082556),+                                    ("first ordinalweek (grain)on <date>", -2.120263536200091)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.7392382877602123, unseen = -5.003946305945459,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)after <time-of-day>", -3.6109179126442243),+                                    ("dayhour", -3.0513021247088017),+                                    ("<ordinal> (as hour)evening|night", -2.5993170009657445),+                                    ("<ordinal> (as hour)on <date>", -4.304065093204169),+                                    ("yesterdayevening|night", -4.304065093204169),+                                    ("hourhour", -1.1470646720540565),+                                    ("after <time-of-day>after <time-of-day>", -3.898599985096005),+                                    ("until <time-of-day>morning", -3.898599985096005),+                                    ("until <time-of-day>after <time-of-day>", -4.304065093204169),+                                    ("minutehour", -4.304065093204169),+                                    ("named-daymorning", -4.304065093204169),+                                    ("todayevening|night", -4.304065093204169),+                                    ("at <time-of-day>evening|night", -4.304065093204169),+                                    ("named-dayevening|night", -4.304065093204169),+                                    ("intersecton <date>", -4.304065093204169),+                                    ("<integer> (latent time-of-day)this <part-of-day>",+                                     -4.304065093204169),+                                    ("hh:mmon <date>", -4.304065093204169),+                                    ("<integer> (latent time-of-day)morning", -3.20545280453606),+                                    ("at <time-of-day>on <date>", -4.304065093204169),+                                    ("intersectmorning", -3.0513021247088017),+                                    ("<integer> (latent time-of-day)evening|night",+                                     -3.0513021247088017),+                                    ("from <datetime> - <datetime> (interval)morning",+                                     -3.898599985096005),+                                    ("from <time-of-day> - <time-of-day> (interval)morning",+                                     -4.304065093204169),+                                    ("on <date>morning", -4.304065093204169),+                                    ("at <time-of-day>morning", -3.898599985096005),+                                    ("tomorrowevening|night", -3.898599985096005)],+                               n = 53},+                   koData =+                     ClassData{prior = -0.6490871907659148,+                               unseen = -5.0689042022202315,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -1.971552579668651),+                                    ("yearhour", -1.9271008170978172),+                                    ("year (latent)on <date>", -4.3694478524670215),+                                    ("<day-of-month> (ordinal)on <date>", -4.3694478524670215),+                                    ("<time-of-day> - <time-of-day> (interval)morning",+                                     -4.3694478524670215),+                                    ("<day-of-month> (ordinal)evening|night", -2.6646997602285962),+                                    ("by the end of <time>morning", -4.3694478524670215),+                                    ("year (latent)evening|night", -3.1166848839716534),+                                    ("hourhour", -2.760009940032921),+                                    ("after <time-of-day>after <time-of-day>", -3.963982744358857),+                                    ("<day-of-month> (ordinal)morning", -3.963982744358857),+                                    ("<day-of-month> (ordinal)after <time-of-day>",+                                     -3.270835563798912),+                                    ("until <time-of-day>morning", -3.4531571205928664),+                                    ("until <time-of-day>after <time-of-day>", -4.3694478524670215),+                                    ("about <time-of-day>after <time-of-day>", -4.3694478524670215),+                                    ("by <time>morning", -4.3694478524670215),+                                    ("<integer> (latent time-of-day)after <time-of-day>",+                                     -3.963982744358857),+                                    ("<integer> (latent time-of-day)morning", -4.3694478524670215),+                                    ("secondhour", -3.1166848839716534),+                                    ("intersectmorning", -3.4531571205928664),+                                    ("from <datetime> - <datetime> (interval)morning",+                                     -3.963982744358857),+                                    ("year (latent)morning", -2.6646997602285962),+                                    ("year (latent)after <time-of-day>", -3.963982744358857),+                                    ("at <time-of-day>after <time-of-day>", -4.3694478524670215)],+                               n = 58}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.14571181118139365,+                               unseen = -4.718498871295094,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -1.5740359853831845),+                                    ("<integer> (latent time-of-day)", -2.3116349285139637),+                                    ("about <time-of-day>", -4.0163830207523885),+                                    ("hh:mm", -3.6109179126442243),+                                    ("<time-of-day> rano", -2.917770732084279),+                                    ("hour", -0.8383291904044432),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -2.2246235515243336),+                                    ("minute", -3.100092288878234)],+                               n = 51},+                   koData =+                     ClassData{prior = -1.9980959022258835, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -1.8325814637483102),+                                    ("<integer> (latent time-of-day)", -1.8325814637483102),+                                    ("relative minutes after|past <integer> (hour-of-day)",+                                     -2.5257286443082556),+                                    ("hour", -1.1394342831883648),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -2.5257286443082556),+                                    ("minute", -2.5257286443082556)],+                               n = 8}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.891820298110627,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 23},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("11th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = -7.79615414697118e-2, unseen = -4.51085950651685,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.890371757896165),+                                    ("<time> <part-of-day>", -3.8066624897703196),+                                    ("intersect", -2.0149030205422647),+                                    ("next <cycle>", -3.1135153092103742),+                                    ("named-month", -2.1972245773362196),+                                    ("half to|till|before <integer> (hour-of-day)",+                                     -3.8066624897703196),+                                    ("day", -2.70805020110221), ("afternoon", -3.1135153092103742),+                                    ("this <cycle>", -2.890371757896165),+                                    ("year", -3.1135153092103742),+                                    ("named-day", -2.890371757896165),+                                    ("hour", -2.3025850929940455), ("month", -1.666596326274049),+                                    ("minute", -3.8066624897703196),+                                    ("this <time>", -3.8066624897703196)],+                               n = 37},+                   koData =+                     ClassData{prior = -2.5902671654458267,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -1.7047480922384253), ("hour", -1.7047480922384253)],+                               n = 3}}),+       ("8th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = -0.3184537311185346, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -0.8649974374866046),+                                    ("<integer> (latent time-of-day)", -2.2512917986064953),+                                    ("hour", -0.7472144018302211)],+                               n = 8},+                   koData =+                     ClassData{prior = -1.2992829841302609,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -1.5040773967762742),+                                    ("<integer> (latent time-of-day)", -1.0986122886681098),+                                    ("hour", -0.8109302162163288)],+                               n = 3}}),+       ("on a named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> <time>",+        Classifier{okData =+                     ClassData{prior = -0.4989911661189879, unseen = -3.951243718581427,+                               likelihoods =+                                 HashMap.fromList+                                   [("second ordinalnamed-dayintersect", -2.833213344056216),+                                    ("first ordinalnamed-dayon <date>", -2.833213344056216),+                                    ("daymonth", -1.4469189829363254),+                                    ("dayyear", -1.9859154836690123),+                                    ("third ordinalnamed-dayintersect", -2.833213344056216),+                                    ("third ordinalintersectyear", -2.833213344056216),+                                    ("third ordinalnamed-dayon <date>", -3.2386784521643803),+                                    ("first ordinalnamed-daynamed-month", -3.2386784521643803),+                                    ("first ordinalintersectyear", -2.833213344056216),+                                    ("first ordinalnamed-dayintersect", -2.833213344056216),+                                    ("second ordinalnamed-dayon <date>", -3.2386784521643803),+                                    ("second ordinalintersectyear", -2.833213344056216)],+                               n = 17},+                   koData =+                     ClassData{prior = -0.9343092373768334,+                               unseen = -3.6888794541139363,+                               likelihoods =+                                 HashMap.fromList+                                   [("third ordinalnamed-daynamed-month", -2.9704144655697013),+                                    ("first ordinalnamed-dayon <date>", -2.9704144655697013),+                                    ("daymonth", -1.717651497074333),+                                    ("14th ordinalnamed-month<integer> (latent time-of-day)",+                                     -2.5649493574615367),+                                    ("monthhour", -1.8718021769015913),+                                    ("second ordinalnamed-daynamed-month", -2.9704144655697013),+                                    ("third ordinalnamed-dayon <date>", -2.9704144655697013),+                                    ("first ordinalnamed-daynamed-month", -2.9704144655697013),+                                    ("ordinal (digits)named-month<integer> (latent time-of-day)",+                                     -2.277267285009756),+                                    ("second ordinalnamed-dayon <date>", -2.9704144655697013)],+                               n = 11}}),+       ("<ordinal> (as hour)",+        Classifier{okData =+                     ClassData{prior = -0.5773153650348236, unseen = -4.454347296253507,+                               likelihoods =+                                 HashMap.fromList+                                   [("11th ordinal", -3.056356895370426),+                                    ("8th ordinal", -3.3440389678222067),+                                    ("21st ordinal no space", -3.7495040759303713),+                                    ("20th ordinal", -3.7495040759303713),+                                    ("third ordinal", -1.8035939268750578),+                                    ("16th ordinal", -3.3440389678222067),+                                    ("18th ordinal", -3.3440389678222067),+                                    ("fifth ordinal", -3.7495040759303713),+                                    ("seventh ordinal", -3.3440389678222067),+                                    ("19th ordinal", -3.3440389678222067),+                                    ("21-29th ordinal", -3.3440389678222067),+                                    ("sixth ordinal", -3.3440389678222067),+                                    ("15th ordinal", -3.3440389678222067),+                                    ("second ordinal", -2.245426679154097),+                                    ("ordinal (digits)", -2.3632097148104805),+                                    ("10th ordinal", -2.496741107435003),+                                    ("9th ordinal", -2.3632097148104805),+                                    ("23rd ordinal no space", -3.7495040759303713)],+                               n = 64},+                   koData =+                     ClassData{prior = -0.8241754429663495, unseen = -4.276666119016055,+                               likelihoods =+                                 HashMap.fromList+                                   [("8th ordinal", -3.164067588373206),+                                    ("20th ordinal", -3.164067588373206),+                                    ("third ordinal", -2.316769727986002),+                                    ("14th ordinal", -3.164067588373206),+                                    ("13th ordinal", -3.56953269648137),+                                    ("15th ordinal", -2.8763855159214247),+                                    ("second ordinal", -2.8763855159214247),+                                    ("ordinal (digits)", -1.1716374236829996),+                                    ("first ordinal", -1.864784604242945)],+                               n = 50}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("21st ordinal no space",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter", -0.916290731874155),+                                    ("third ordinalquarter (grain)", -0.916290731874155)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -0.916290731874155),+                                    ("quarter", -0.916290731874155)],+                               n = 1}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.7200546334798696, unseen = -6.364750756851911,+                               likelihoods =+                                 HashMap.fromList+                                   [("<datetime> - <datetime> (interval)on <date>",+                                     -5.264415814872355),+                                    ("mm/dd<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -5.66988092298052),+                                    ("<hour-of-day> - <hour-of-day> (interval)on <date>",+                                     -5.264415814872355),+                                    ("named-daynamed-month", -4.7535901911063645),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -5.264415814872355),+                                    ("hourday", -3.8781214537524646),+                                    ("dayhour", -2.6741486494265287),+                                    ("daymonth", -3.8781214537524646),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyabsorption of , after named day",+                                     -4.7535901911063645),+                                    ("monthyear", -3.1849742731925192),+                                    ("from <hour-of-day> - <hour-of-day> (interval)on a named-day",+                                     -5.66988092298052),+                                    ("from <time-of-day> - <time-of-day> (interval)on a named-day",+                                     -5.66988092298052),+                                    ("absorption of , after named dayintersect by \",\" 2",+                                     -5.264415814872355),+                                    ("intersecthh:mm", -5.264415814872355),+                                    ("from <datetime> - <datetime> (interval)on a named-day",+                                     -5.66988092298052),+                                    ("at <time-of-day>intersect by \",\" 2", -5.264415814872355),+                                    ("named-daylast <cycle>", -5.264415814872355),+                                    ("named-day<time-of-day> rano", -5.66988092298052),+                                    ("on a named-dayat <time-of-day>", -5.264415814872355),+                                    ("at <time-of-day>named-day", -5.264415814872355),+                                    ("at <time-of-day>on a named-day", -5.66988092298052),+                                    ("<time> <part-of-day>on a named-day", -5.264415814872355),+                                    ("on a named-day<time> <part-of-day>", -5.66988092298052),+                                    ("last <day-of-week> of <time>year", -5.66988092298052),+                                    ("today<time> <part-of-day>", -5.66988092298052),+                                    ("todayat <time-of-day>", -5.66988092298052),+                                    ("on <date>at <time-of-day>", -5.264415814872355),+                                    ("dayday", -2.995732273553991),+                                    ("on <date><time> <part-of-day>", -5.66988092298052),+                                    ("intersect by \",\"hh:mm", -4.4171179544851515),+                                    ("mm/ddat <time-of-day>", -4.976733742420574),+                                    ("last <cycle> <time>year", -4.7535901911063645),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -4.976733742420574),+                                    ("intersect<day-of-month> (non ordinal) <named-month>",+                                     -4.976733742420574),+                                    ("dayyear", -3.654977902438255),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -5.264415814872355),+                                    ("day-after-tomorrow (single-word)at <time-of-day>",+                                     -5.66988092298052),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month>",+                                     -4.165803526204246),+                                    ("tomorrow<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -5.66988092298052),+                                    ("named-monthyear", -3.529814759484249),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.283586561860629),+                                    ("tomorrowuntil <time-of-day>", -5.264415814872355),+                                    ("absorption of , after named day<day-of-month> (non ordinal) <named-month>",+                                     -4.165803526204246),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect by \",\"",+                                     -4.7535901911063645),+                                    ("named-dayin <duration>", -5.66988092298052),+                                    ("last <day-of-week> <time>year", -5.264415814872355),+                                    ("<time-of-day> ranoon <date>", -5.264415814872355),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.283586561860629),+                                    ("named-daynext <cycle>", -4.7535901911063645),+                                    ("named-dayintersect", -5.264415814872355),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.976733742420574),+                                    ("on <date><time-of-day> rano", -5.66988092298052),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocytomorrow",+                                     -5.66988092298052),+                                    ("from <time-of-day> - <time-of-day> (interval)on <date>",+                                     -5.66988092298052),+                                    ("at <time-of-day>intersect", -5.264415814872355),+                                    ("dayminute", -3.318505665817042),+                                    ("intersect by \",\" 2hh:mm", -4.4171179544851515),+                                    ("<time-of-day> ranoon a named-day", -5.264415814872355),+                                    ("from <hour-of-day> - <hour-of-day> (interval)on <date>",+                                     -5.66988092298052),+                                    ("from <datetime> - <datetime> (interval)on <date>",+                                     -5.66988092298052),+                                    ("intersectyear", -5.264415814872355),+                                    ("on a named-day<time-of-day> rano", -5.66988092298052),+                                    ("<ordinal> <cycle> of <time>year", -5.66988092298052),+                                    ("minuteday", -2.3556949183079943),+                                    ("absorption of , after named dayintersect",+                                     -5.264415814872355),+                                    ("named-dayon <date>", -4.060443010546419),+                                    ("named-day<time> <part-of-day>", -4.7535901911063645),+                                    ("named-dayat <time-of-day>", -5.264415814872355),+                                    ("yearhh:mm", -5.66988092298052),+                                    ("at <time-of-day>intersect by \",\"", -5.264415814872355),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -5.264415814872355),+                                    ("tomorrowexactly <time-of-day>", -4.976733742420574),+                                    ("at <time-of-day>absorption of , after named day",+                                     -5.264415814872355),+                                    ("at <time-of-day>on <date>", -5.66988092298052),+                                    ("on <date>year", -4.283586561860629),+                                    ("dayweek", -3.7239707739252066),+                                    ("<time> <part-of-day>on <date>", -5.264415814872355),+                                    ("weekyear", -4.4171179544851515),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -4.976733742420574),+                                    ("<ordinal> <cycle> <time>year", -5.264415814872355),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect by \",\" 2",+                                     -4.7535901911063645),+                                    ("tomorrowat <time-of-day>", -5.66988092298052),+                                    ("named-daythis <cycle>", -5.264415814872355),+                                    ("tomorrow<time> <part-of-day>", -5.66988092298052),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect",+                                     -4.7535901911063645),+                                    ("<named-month> <day-of-month> (ordinal)year",+                                     -5.66988092298052),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocynamed-day",+                                     -4.7535901911063645),+                                    ("tomorrow<time-of-day> rano", -5.66988092298052),+                                    ("<datetime> - <datetime> (interval)on a named-day",+                                     -5.264415814872355),+                                    ("last <cycle> of <time>year", -5.264415814872355),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -5.66988092298052),+                                    ("<time-of-day> - <time-of-day> (interval)on a named-day",+                                     -5.264415814872355),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -5.264415814872355),+                                    ("<hour-of-day> - <hour-of-day> (interval)on a named-day",+                                     -5.264415814872355),+                                    ("yearminute", -5.66988092298052)],+                               n = 220},+                   koData =+                     ClassData{prior = -0.6669448081659212, unseen = -6.405228458030842,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)<named-month> <day-of-month> (non ordinal)",+                                     -4.61181472870676),+                                    ("<time-of-day> ranoby <time>", -5.304961909266705),+                                    ("intersect by \",\"named-month", -4.206349620598596),+                                    ("named-daynamed-month", -5.304961909266705),+                                    ("hourday", -2.7926562852905903),+                                    ("dayhour", -3.107737331930486),+                                    ("daymonth", -3.312531744576499),+                                    ("monthday", -5.304961909266705),+                                    ("monthyear", -4.794136285500715),+                                    ("named-month<hour-of-day> <integer> (as relative minutes)",+                                     -5.71042701737487),+                                    ("at <time-of-day>intersect by \",\" 2", -5.71042701737487),+                                    ("houryear", -3.570360853878599),+                                    ("<time> <part-of-day>until <time-of-day>", -5.304961909266705),+                                    ("<ordinal> (as hour)intersect", -3.145477659913333),+                                    ("monthhour", -4.61181472870676),+                                    ("<time> <part-of-day><time> <part-of-day>",+                                     -5.017279836814924),+                                    ("hourmonth", -2.0860860843985045),+                                    ("mm/ddat <time-of-day>", -5.71042701737487),+                                    ("hourhour", -4.794136285500715),+                                    ("<time> <part-of-day>by <time>", -5.304961909266705),+                                    ("intersectnamed-month", -3.4591352187683744),+                                    ("dayyear", -4.457664048879502),+                                    ("<time-of-day> ranoby the end of <time>", -5.304961909266705),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -5.304961909266705),+                                    ("intersect by \",\" 2named-month", -4.206349620598596),+                                    ("monthminute", -5.304961909266705),+                                    ("minutemonth", -5.017279836814924),+                                    ("named-monthyear", -4.794136285500715),+                                    ("absorption of , after named daynamed-month",+                                     -4.324132656254979),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect by \",\"",+                                     -5.304961909266705),+                                    ("after <time-of-day>at <time-of-day>", -5.71042701737487),+                                    ("hh:mmby the end of <time>", -5.71042701737487),+                                    ("<ordinal> (as hour)named-month", -3.036278367948341),+                                    ("daysecond", -5.304961909266705),+                                    ("<time> <part-of-day>by the end of <time>",+                                     -5.304961909266705),+                                    ("named-month<ordinal> (as hour)", -4.794136285500715),+                                    ("<time> <part-of-day><time-of-day> rano", -5.71042701737487),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -5.71042701737487),+                                    ("named-dayintersect", -4.100989104940769),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -5.71042701737487),+                                    ("<time-of-day> rano<time> <part-of-day>", -5.304961909266705),+                                    ("at <time-of-day>intersect", -5.71042701737487),+                                    ("dayminute", -5.304961909266705),+                                    ("<named-month> <day-of-month> (non ordinal)by <time>",+                                     -5.71042701737487),+                                    ("intersecton <date>", -4.324132656254979),+                                    ("intersectyear", -3.312531744576499),+                                    ("minuteday", -3.7645168683195562),+                                    ("absorption of , after named dayintersect",+                                     -4.206349620598596),+                                    ("<ordinal> (as hour)year", -5.71042701737487),+                                    ("named-dayon <date>", -4.794136285500715),+                                    ("hh:mmon <date>", -5.304961909266705),+                                    ("absorption of , after named day<ordinal> (as hour)",+                                     -4.206349620598596),+                                    ("at <time-of-day>intersect by \",\"", -5.71042701737487),+                                    ("<named-month> <day-of-month> (non ordinal)by the end of <time>",+                                     -5.71042701737487),+                                    ("tomorrowexactly <time-of-day>", -5.71042701737487),+                                    ("hoursecond", -3.8386248404732783),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -5.304961909266705),+                                    ("named-day<ordinal> (as hour)", -5.017279836814924),+                                    ("<ordinal> (as hour)named-day", -4.206349620598596),+                                    ("named-monthrelative minutes to|till|before <integer> (hour-of-day)",+                                     -5.71042701737487),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -5.304961909266705),+                                    ("intersectintersect", -4.457664048879502),+                                    ("hh:mmon a named-day", -5.304961909266705),+                                    ("named-monthintersect", -5.71042701737487),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect by \",\" 2",+                                     -5.304961909266705),+                                    ("hh:mmby <time>", -5.71042701737487),+                                    ("tomorrowat <time-of-day>", -5.71042701737487),+                                    ("minutesecond", -5.304961909266705),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocyintersect",+                                     -5.304961909266705),+                                    ("yearminute", -5.304961909266705)],+                               n = 232}}),+       ("half after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("twenty",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("20th ordinal",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("a few",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7047480922384253),+                                    ("first ordinalweek (grain)named-month", -1.7047480922384253),+                                    ("weekmonth", -1.2992829841302609),+                                    ("first ordinalweek (grain)intersect", -1.7047480922384253),+                                    ("third ordinalday (grain)named-month", -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = -1.0116009116784799, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 16},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.7537718023763802,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day><integer> (latent time-of-day)",+                                     -2.70805020110221),+                                    ("minuteminute", -2.3025850929940455),+                                    ("<time> <part-of-day><time> <part-of-day>", -2.70805020110221),+                                    ("<time-of-day> rano<time-of-day> rano", -2.70805020110221),+                                    ("hh:mmhh:mm", -2.3025850929940455),+                                    ("hourhour", -1.455287232606842),+                                    ("<time> <part-of-day><time-of-day> rano", -2.70805020110221),+                                    ("<time-of-day> rano<time> <part-of-day>", -2.70805020110221),+                                    ("<time-of-day> rano<integer> (latent time-of-day)",+                                     -2.70805020110221)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.6359887667199967,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day><integer> (latent time-of-day)",+                                     -2.772588722239781),+                                    ("houryear", -2.772588722239781),+                                    ("minuteminute", -2.367123614131617),+                                    ("<time> <part-of-day><time> <part-of-day>",+                                     -2.367123614131617),+                                    ("hourhour", -1.8562979903656263),+                                    ("minutehour", -2.367123614131617),+                                    ("hh:mmintersect", -2.367123614131617),+                                    ("<time> <part-of-day>year (latent)", -2.772588722239781),+                                    ("<time> <part-of-day><time-of-day> rano", -2.772588722239781),+                                    ("hh:mm<integer> (latent time-of-day)", -2.367123614131617)],+                               n = 9}}),+       ("from <hour-of-day> - <hour-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.6931471805599453),+                                    ("hh:mmhh:mm", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("month (grain)", -3.044522437723423),+                                    ("year (grain)", -2.639057329615259),+                                    ("second", -3.044522437723423),+                                    ("week (grain)", -1.540445040947149),+                                    ("quarter", -2.3513752571634776), ("year", -2.639057329615259),+                                    ("second (grain)", -3.044522437723423),+                                    ("month", -3.044522437723423),+                                    ("quarter (grain)", -2.3513752571634776)],+                               n = 15},+                   koData =+                     ClassData{prior = -2.772588722239781, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("minute (grain)", -1.9459101490553135),+                                    ("minute", -1.9459101490553135)],+                               n = 1}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.6094379124341003),+                                    ("<time-of-day> rano<time-of-day> rano", -2.0149030205422647),+                                    ("hh:mmhh:mm", -1.6094379124341003),+                                    ("hourhour", -1.6094379124341003),+                                    ("<time-of-day> rano<integer> (latent time-of-day)",+                                     -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("minutehour", -1.2992829841302609),+                                    ("hh:mm<integer> (latent time-of-day)", -1.2992829841302609)],+                               n = 2}}),+       ("integer 21..99",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods =+                                 HashMap.fromList [("integer (numeric)integer (numeric)", 0.0)],+                               n = 1}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -8.004270767353637e-2),+                                    ("one", -2.5649493574615367)],+                               n = 24}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening|night",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("third ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -0.6931471805599453),+                                    ("ordinal (digits)quarter (grain)year", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\" 2",+        Classifier{okData =+                     ClassData{prior = -0.46430560813109784, unseen = -4.74493212836325,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect by \",\"year", -4.04305126783455),+                                    ("intersect by \",\" 2intersect", -4.04305126783455),+                                    ("dayday", -1.4781019103730135),+                                    ("named-dayintersect by \",\"", -3.6375861597263857),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -3.349904087274605),+                                    ("intersect<day-of-month> (non ordinal) <named-month>",+                                     -3.349904087274605),+                                    ("dayyear", -2.9444389791664407),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -4.04305126783455),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -2.538973871058276),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.6567569067146595),+                                    ("intersect by \",\"intersect", -4.04305126783455),+                                    ("named-dayintersect", -3.6375861597263857),+                                    ("intersect by \",\" 2year", -4.04305126783455),+                                    ("named-dayintersect by \",\" 2", -3.6375861597263857),+                                    ("dayminute", -2.538973871058276),+                                    ("intersectyear", -4.04305126783455),+                                    ("minuteday", -2.790288299339182),+                                    ("intersectintersect", -4.04305126783455),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -2.538973871058276),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.6375861597263857)],+                               n = 44},+                   koData =+                     ClassData{prior = -0.9903987040278769,+                               unseen = -4.3694478524670215,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.277267285009756),+                                    ("dayhour", -1.5234954826333758),+                                    ("daymonth", -2.277267285009756),+                                    ("intersectnamed-month", -2.9704144655697013),+                                    ("minutemonth", -2.9704144655697013),+                                    ("named-dayintersect", -2.159484249353372),+                                    ("named-day<ordinal> (as hour)", -2.159484249353372)],+                               n = 26}}),+       ("16th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -1.791759469228055),+                                    ("<integer> (latent time-of-day)", -1.791759469228055),+                                    ("noon", -1.3862943611198906), ("hour", -0.8754687373538999)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> (latent time-of-day)",+        Classifier{okData =+                     ClassData{prior = -0.505548566665147, unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -7.598590697792199e-2),+                                    ("fifteen", -3.0204248861443626)],+                               n = 38},+                   koData =+                     ClassData{prior = -0.924258901523332, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.15415067982725836),+                                    ("one", -2.639057329615259), ("fifteen", -2.639057329615259)],+                               n = 25}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("second ordinalnamed-dayintersect", -2.0149030205422647),+                                    ("daymonth", -1.0986122886681098),+                                    ("third ordinalnamed-dayintersect", -2.0149030205422647),+                                    ("first ordinalnamed-daynamed-month", -2.0149030205422647),+                                    ("first ordinalnamed-dayintersect", -2.0149030205422647)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("third ordinalnamed-daynamed-month", -1.8718021769015913),+                                    ("daymonth", -1.1786549963416462),+                                    ("second ordinalnamed-daynamed-month", -1.8718021769015913),+                                    ("first ordinalnamed-daynamed-month", -1.8718021769015913)],+                               n = 3}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.51085950651685,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 89},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("18th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.784189633918261,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 42},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("fifth ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("valentine's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <day-of-week> <time>",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.791759469228055),+                                    ("daymonth", -0.9444616088408514),+                                    ("named-dayintersect", -1.791759469228055),+                                    ("named-dayon <date>", -1.791759469228055)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayin <duration>", -1.3862943611198906),+                                    ("dayminute", -1.3862943611198906)],+                               n = 1}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("<unit-of-duration> as a duration",+        Classifier{okData =+                     ClassData{prior = -2.3608540011180215,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6314168191528755),+                                    ("hour (grain)", -2.7300291078209855),+                                    ("second", -2.4423470353692043),+                                    ("week (grain)", -1.6314168191528755),+                                    ("day", -3.1354942159291497),+                                    ("minute (grain)", -3.1354942159291497),+                                    ("second (grain)", -2.4423470353692043),+                                    ("hour", -2.7300291078209855), ("minute", -3.1354942159291497),+                                    ("day (grain)", -3.1354942159291497)],+                               n = 15},+                   koData =+                     ClassData{prior = -9.909090264423089e-2,+                               unseen = -5.720311776607412,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.161679639916808),+                                    ("month (grain)", -3.2321210516182215),+                                    ("hour (grain)", -2.7212954278522306),+                                    ("year (grain)", -2.8838143573500057),+                                    ("second", -2.8838143573500057),+                                    ("week (grain)", -2.161679639916808),+                                    ("day", -2.498151876538021), ("quarter", -3.5198031240700023),+                                    ("minute (grain)", -2.8838143573500057),+                                    ("year", -2.8838143573500057),+                                    ("second (grain)", -2.8838143573500057),+                                    ("hour", -2.7212954278522306), ("month", -3.2321210516182215),+                                    ("quarter (grain)", -3.5198031240700023),+                                    ("minute", -2.8838143573500057),+                                    ("day (grain)", -2.498151876538021)],+                               n = 144}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -1.5040773967762742),+                                    ("evening|night", -1.0986122886681098),+                                    ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("christmas eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.19671029424605427,+                               unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("third ordinalnamed-month", -3.295836866004329),+                                    ("8th ordinalnamed-month", -2.890371757896165),+                                    ("first ordinalnamed-month", -2.890371757896165),+                                    ("15th ordinalnamed-month", -2.890371757896165),+                                    ("ordinal (digits)named-month", -1.2163953243244932),+                                    ("month", -0.8109302162163288),+                                    ("13th ordinalnamed-month", -3.295836866004329)],+                               n = 23},+                   koData =+                     ClassData{prior = -1.7227665977411035,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("14th ordinalnamed-month", -1.791759469228055),+                                    ("ordinal (digits)named-month", -1.5040773967762742),+                                    ("month", -1.0986122886681098)],+                               n = 5}}),+       ("<duration> hence",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3121863889661687),+                                    ("<unit-of-duration> as a duration", -1.8718021769015913),+                                    ("day", -2.159484249353372), ("year", -2.5649493574615367),+                                    ("<integer> <unit-of-duration>", -1.1786549963416462),+                                    ("month", -2.5649493574615367)],+                               n = 10},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.0794415416798357),+                                    ("<unit-of-duration> as a duration", -0.9808292530117262),+                                    ("day", -1.6739764335716716), ("year", -2.0794415416798357),+                                    ("month", -2.0794415416798357)],+                               n = 5}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 11}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("<cycle> after <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day (grain)tomorrow", -0.6931471805599453),+                                    ("dayday", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("Mother's Day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.3862943611198906),+                                    ("day", -1.3862943611198906),+                                    ("named-day", -1.3862943611198906),+                                    ("month", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.9444389791664407),+                                    ("<ordinal> (as hour)", -2.538973871058276),+                                    ("year (latent)", -2.9444389791664407),+                                    ("<integer> (latent time-of-day)", -2.0281482472922856),+                                    ("day", -2.538973871058276), ("year", -2.9444389791664407),+                                    ("hh:mm", -2.9444389791664407),+                                    ("<day-of-month> (ordinal)", -2.538973871058276),+                                    ("noon", -2.9444389791664407),+                                    ("<time-of-day> rano", -2.9444389791664407),+                                    ("hour", -1.3350010667323402), ("minute", -2.9444389791664407)],+                               n = 13}}),+       ("seventh ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("one",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("<duration> from now",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("second", -1.9459101490553135),+                                    ("<unit-of-duration> as a duration", -1.540445040947149),+                                    ("day", -1.9459101490553135), ("year", -1.9459101490553135),+                                    ("<integer> <unit-of-duration>", -1.540445040947149),+                                    ("minute", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<unit-of-duration> as a duration", -1.2039728043259361),+                                    ("year", -1.6094379124341003), ("minute", -1.6094379124341003)],+                               n = 2}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.8066624897703196,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5869650565820417),+                                    ("year (grain)", -1.9924301646902063),+                                    ("week (grain)", -1.5869650565820417),+                                    ("day", -2.6855773452501515), ("quarter", -2.3978952727983707),+                                    ("year", -1.9924301646902063),+                                    ("quarter (grain)", -2.3978952727983707),+                                    ("day (grain)", -2.6855773452501515)],+                               n = 18},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = -0.3483066942682157, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -1.2237754316221157,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5}}),+       ("last <cycle> <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.540445040947149),+                                    ("week (grain)named-month", -2.639057329615259),+                                    ("day (grain)intersect", -2.2335922215070942),+                                    ("day (grain)on <date>", -2.2335922215070942),+                                    ("weekmonth", -1.540445040947149),+                                    ("day (grain)named-month", -2.639057329615259),+                                    ("week (grain)intersect", -2.2335922215070942),+                                    ("week (grain)on <date>", -2.2335922215070942)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -2.4423470353692043),+                                    ("<ordinal> (as hour)", -1.5260563034950494),+                                    ("<integer> (latent time-of-day)", -2.03688192726104),+                                    ("hour", -0.9382696385929302),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -2.4423470353692043)],+                               n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("relative minutes after|past <integer> (hour-of-day)",+                                     -1.5040773967762742),+                                    ("minute", -1.5040773967762742)],+                               n = 1}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.14842000511827333,+                               unseen = -3.295836866004329,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 25},+                   koData =+                     ClassData{prior = -1.9810014688665833, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.252762968495368),+                                    ("daymonth", -0.8472978603872037),+                                    ("named-dayintersect", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.7404000654104909, unseen = -4.59511985013459,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.2823823856765264),+                                    ("threemonth (grain)", -3.4863551900024623),+                                    ("fifteenminute (grain)", -3.891820298110627),+                                    ("a fewhour (grain)", -3.891820298110627),+                                    ("integer (numeric)day (grain)", -2.793208009442517),+                                    ("twoweek (grain)", -3.891820298110627),+                                    ("fiveday (grain)", -3.891820298110627),+                                    ("oneweek (grain)", -3.1986731175506815),+                                    ("oneminute (grain)", -3.891820298110627),+                                    ("integer (numeric)year (grain)", -3.891820298110627),+                                    ("day", -2.505525936990736), ("year", -3.1986731175506815),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("oneday (grain)", -3.891820298110627),+                                    ("hour", -3.1986731175506815), ("month", -3.4863551900024623),+                                    ("threeweek (grain)", -3.4863551900024623),+                                    ("integer (numeric)minute (grain)", -2.793208009442517),+                                    ("minute", -2.505525936990736),+                                    ("integer (numeric)hour (grain)", -3.4863551900024623),+                                    ("twoyear (grain)", -3.4863551900024623)],+                               n = 31},+                   koData =+                     ClassData{prior = -0.6480267452794757, unseen = -4.653960350157523,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.8526314299133175),+                                    ("threemonth (grain)", -3.951243718581427),+                                    ("threehour (grain)", -3.951243718581427),+                                    ("integer (numeric)day (grain)", -3.258096538021482),+                                    ("twoweek (grain)", -3.951243718581427),+                                    ("twominute (grain)", -3.951243718581427),+                                    ("second", -2.6984807500860595),+                                    ("threeday (grain)", -3.951243718581427),+                                    ("threeyear (grain)", -3.951243718581427),+                                    ("integer (numeric)second (grain)", -3.0349529867072724),+                                    ("twomonth (grain)", -3.951243718581427),+                                    ("onehour (grain)", -3.951243718581427),+                                    ("integer (numeric)year (grain)", -3.545778610473263),+                                    ("threesecond (grain)", -3.951243718581427),+                                    ("day", -2.6984807500860595), ("year", -3.0349529867072724),+                                    ("threeminute (grain)", -3.951243718581427),+                                    ("integer (numeric)week (grain)", -3.258096538021482),+                                    ("twoday (grain)", -3.951243718581427),+                                    ("hour", -2.6984807500860595), ("month", -3.258096538021482),+                                    ("threeweek (grain)", -3.951243718581427),+                                    ("integer (numeric)minute (grain)", -3.545778610473263),+                                    ("a fewday (grain)", -3.951243718581427),+                                    ("integer (numeric)month (grain)", -3.951243718581427),+                                    ("minute", -3.0349529867072724),+                                    ("twosecond (grain)", -3.951243718581427),+                                    ("integer (numeric)hour (grain)", -3.258096538021482),+                                    ("fifteenhour (grain)", -3.951243718581427),+                                    ("twoyear (grain)", -3.951243718581427)],+                               n = 34}}),+       ("19th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("thanksgiving day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> after <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.6931471805599453),+                                    ("<unit-of-duration> as a durationtomorrow",+                                     -0.6931471805599453)],+                               n = 1}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)<integer> (latent time-of-day)",+                                     -1.7047480922384253),+                                    ("fifteen<ordinal> (as hour)", -1.7047480922384253),+                                    ("hour", -1.0116009116784799),+                                    ("integer (numeric)<ordinal> (as hour)", -1.7047480922384253)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)noon", -1.0986122886681098),+                                    ("hour", -1.0986122886681098)],+                               n = 2}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.46430560813109784, unseen = -4.74493212836325,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect by \",\"year", -4.04305126783455),+                                    ("intersect by \",\" 2intersect", -4.04305126783455),+                                    ("dayday", -1.4781019103730135),+                                    ("named-dayintersect by \",\"", -3.6375861597263857),+                                    ("intersect<named-month> <day-of-month> (non ordinal)",+                                     -3.349904087274605),+                                    ("intersect<day-of-month> (non ordinal) <named-month>",+                                     -3.349904087274605),+                                    ("dayyear", -2.9444389791664407),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -4.04305126783455),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -2.538973871058276),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -2.6567569067146595),+                                    ("intersect by \",\"intersect", -4.04305126783455),+                                    ("named-dayintersect", -3.6375861597263857),+                                    ("intersect by \",\" 2year", -4.04305126783455),+                                    ("named-dayintersect by \",\" 2", -3.6375861597263857),+                                    ("dayminute", -2.538973871058276),+                                    ("intersectyear", -4.04305126783455),+                                    ("minuteday", -2.790288299339182),+                                    ("intersectintersect", -4.04305126783455),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -2.538973871058276),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.6375861597263857)],+                               n = 44},+                   koData =+                     ClassData{prior = -0.9903987040278769,+                               unseen = -4.3694478524670215,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -2.277267285009756),+                                    ("dayhour", -1.5234954826333758),+                                    ("daymonth", -2.277267285009756),+                                    ("intersectnamed-month", -2.9704144655697013),+                                    ("minutemonth", -2.9704144655697013),+                                    ("named-dayintersect", -2.159484249353372),+                                    ("named-day<ordinal> (as hour)", -2.159484249353372)],+                               n = 26}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -4.652001563489282e-2,+                               unseen = -3.1354942159291497,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 21},+                   koData =+                     ClassData{prior = -3.0910424533583156,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("14th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("21-29th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("second ordinal", -0.6931471805599453),+                                    ("first ordinal", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.584967478670572,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 96},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> before <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.6931471805599453),+                                    ("<unit-of-duration> as a durationyesterday",+                                     -0.6931471805599453)],+                               n = 1}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = -0.9985288301111273,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -0.4595323293784402, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12}}),+       ("13th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daylast <cycle>", -0.6931471805599453),+                                    ("dayweek", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3121863889661687),+                                    ("<unit-of-duration> as a duration", -1.8718021769015913),+                                    ("day", -2.159484249353372), ("year", -2.5649493574615367),+                                    ("<integer> <unit-of-duration>", -1.1786549963416462),+                                    ("month", -2.5649493574615367)],+                               n = 10},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.0794415416798357),+                                    ("<unit-of-duration> as a duration", -0.9808292530117262),+                                    ("day", -1.6739764335716716), ("year", -2.0794415416798357),+                                    ("month", -2.0794415416798357)],+                               n = 5}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.1631508098056809),+                                    ("named-day", -1.1631508098056809)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.2231435513142097, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> o'clock", -2.5902671654458267),+                                    ("intersect", -2.3025850929940455),+                                    ("year (latent)", -2.0794415416798357),+                                    ("<integer> (latent time-of-day)", -2.0794415416798357),+                                    ("day", -1.742969305058623), ("year", -2.0794415416798357),+                                    ("named-day", -2.3025850929940455),+                                    ("hour", -1.742969305058623)],+                               n = 16}}),+       ("sixth ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("11th ordinal", -2.2335922215070942),+                                    ("8th ordinal", -2.639057329615259),+                                    ("third ordinal", -2.2335922215070942),+                                    ("16th ordinal", -2.639057329615259),+                                    ("second ordinal", -1.7227665977411035),+                                    ("ordinal (digits)", -2.2335922215070942),+                                    ("10th ordinal", -1.7227665977411035),+                                    ("9th ordinal", -1.7227665977411035)],+                               n = 20}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -1.791759469228055, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.1823215567939546,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -3.6375861597263857,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.2246235515243336),+                                    ("<ordinal> (as hour)", -2.512305623976115),+                                    ("<integer> (latent time-of-day)", -2.512305623976115),+                                    ("<time-of-day> rano", -2.512305623976115),+                                    ("hour", -1.213022639845854),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -2.917770732084279)],+                               n = 10},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -4.060443010546419,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.2512917986064953),+                                    ("<ordinal> (as hour)", -2.9444389791664407),+                                    ("year (latent)", -2.6567569067146595),+                                    ("yesterday", -3.349904087274605),+                                    ("<integer> (latent time-of-day)", -3.349904087274605),+                                    ("day", -2.9444389791664407), ("year", -2.6567569067146595),+                                    ("hh:mm", -3.349904087274605),+                                    ("<day-of-month> (ordinal)", -3.349904087274605),+                                    ("noon", -2.9444389791664407),+                                    ("<time-of-day> rano", -3.349904087274605),+                                    ("hour", -1.3350010667323402),+                                    ("<datetime> - <datetime> (interval)", -3.349904087274605),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -3.349904087274605),+                                    ("<hour-of-day> - <hour-of-day> (interval)",+                                     -3.349904087274605),+                                    ("minute", -3.349904087274605)],+                               n = 20}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> rano",+        Classifier{okData =+                     ClassData{prior = -0.10008345855698253,+                               unseen = -3.828641396489095,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -2.0149030205422647),+                                    ("<ordinal> (as hour)", -2.70805020110221),+                                    ("<integer> (latent time-of-day)", -1.5040773967762742),+                                    ("hh:mm", -3.1135153092103742),+                                    ("until <time-of-day>", -2.70805020110221),+                                    ("hour", -0.8622235106038793), ("minute", -3.1135153092103742)],+                               n = 19},+                   koData =+                     ClassData{prior = -2.3513752571634776,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -1.7047480922384253),+                                    ("until <time-of-day>", -1.7047480922384253),+                                    ("hour", -1.2992829841302609)],+                               n = 2}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("decimal number",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -2.4849066497880004),+                                    ("day", -0.8754687373538999),+                                    ("named-day", -0.8754687373538999),+                                    ("month", -2.4849066497880004)],+                               n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("month (grain)", -1.6739764335716716),+                                    ("year (grain)", -2.367123614131617),+                                    ("week (grain)", -1.6739764335716716),+                                    ("year", -2.367123614131617), ("month", -1.6739764335716716)],+                               n = 12},+                   koData =+                     ClassData{prior = -1.3862943611198906, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("week (grain)", -1.6739764335716716),+                                    ("day", -1.6739764335716716),+                                    ("day (grain)", -1.6739764335716716)],+                               n = 4}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.793208009442517),+                                    ("threemonth (grain)", -3.1986731175506815),+                                    ("threehour (grain)", -3.1986731175506815),+                                    ("integer (numeric)day (grain)", -3.1986731175506815),+                                    ("second", -2.793208009442517),+                                    ("threeday (grain)", -3.1986731175506815),+                                    ("threeyear (grain)", -3.1986731175506815),+                                    ("integer (numeric)second (grain)", -3.1986731175506815),+                                    ("integer (numeric)year (grain)", -3.1986731175506815),+                                    ("threesecond (grain)", -3.1986731175506815),+                                    ("day", -2.505525936990736), ("year", -2.793208009442517),+                                    ("threeminute (grain)", -3.1986731175506815),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("hour", -2.793208009442517), ("month", -3.1986731175506815),+                                    ("threeweek (grain)", -3.1986731175506815),+                                    ("integer (numeric)minute (grain)", -3.1986731175506815),+                                    ("a fewday (grain)", -3.1986731175506815),+                                    ("minute", -2.793208009442517),+                                    ("integer (numeric)hour (grain)", -3.1986731175506815)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("15th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("halloween day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("by the end of <time>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.9444389791664407),+                                    ("<ordinal> (as hour)", -2.538973871058276),+                                    ("year (latent)", -2.9444389791664407),+                                    ("<integer> (latent time-of-day)", -2.0281482472922856),+                                    ("day", -2.538973871058276), ("year", -2.9444389791664407),+                                    ("hh:mm", -2.9444389791664407),+                                    ("<day-of-month> (ordinal)", -2.538973871058276),+                                    ("noon", -2.9444389791664407),+                                    ("<time-of-day> rano", -2.9444389791664407),+                                    ("hour", -1.3350010667323402), ("minute", -2.9444389791664407)],+                               n = 13}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097, unseen = -4.0943445622221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.691243082785829),+                                    ("number.number hours", -3.3843902633457743),+                                    ("second", -2.9789251552376097),+                                    ("<unit-of-duration> as a duration", -1.9980959022258835),+                                    ("day", -2.9789251552376097),+                                    ("half an hour", -3.3843902633457743),+                                    ("<integer> <unit-of-duration>", -1.5125880864441827),+                                    ("<integer> and an half hours", -3.3843902633457743),+                                    ("hour", -2.2857779746776643), ("minute", -1.5125880864441827),+                                    ("about <duration>", -2.9789251552376097)],+                               n = 24},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.749199854809259), ("second", -2.03688192726104),+                                    ("<unit-of-duration> as a duration", -1.5260563034950494),+                                    ("<integer> <unit-of-duration>", -2.03688192726104),+                                    ("minute", -2.4423470353692043)],+                               n = 6}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.6739764335716716,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.824549292051046),+                                    ("hh:mmhh:mm", -1.824549292051046),+                                    ("dayday", -2.3353749158170367),+                                    ("<named-month> <day-of-month> (non ordinal)<named-month> <day-of-month> (non ordinal)",+                                     -2.3353749158170367)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.2076393647782445, unseen = -4.276666119016055,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -3.164067588373206),+                                    ("about <time-of-day>noon", -3.56953269648137),+                                    ("minuteminute", -2.4709204078132605),+                                    ("<time> <part-of-day><time> <part-of-day>",+                                     -2.8763855159214247),+                                    ("<time-of-day> rano<time-of-day> rano", -3.56953269648137),+                                    ("until <time-of-day>noon", -3.56953269648137),+                                    ("hh:mmhh:mm", -3.56953269648137),+                                    ("hourhour", -1.3723081191451507),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -3.164067588373206),+                                    ("after <time-of-day>noon", -3.164067588373206),+                                    ("hh:mmintersect", -2.653241964607215),+                                    ("<time> <part-of-day><time-of-day> rano", -3.164067588373206),+                                    ("at <time-of-day>noon", -3.56953269648137),+                                    ("<time-of-day> rano<time> <part-of-day>", -3.56953269648137),+                                    ("<ordinal> (as hour)noon", -2.4709204078132605),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -3.164067588373206),+                                    ("yearminute", -3.164067588373206)],+                               n = 26}}),+       ("second ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> popo\322udniu/wieczorem/w nocy",+        Classifier{okData =+                     ClassData{prior = -1.5037877364540559e-2,+                               unseen = -4.962844630259907,+                               likelihoods =+                                 HashMap.fromList+                                   [("exactly <time-of-day>", -4.2626798770413155),+                                    ("at <time-of-day>", -2.4709204078132605),+                                    ("<ordinal> (as hour)", -1.5218398531161146),+                                    ("<integer> (latent time-of-day)", -2.01138807843482),+                                    ("about <time-of-day>", -4.2626798770413155),+                                    ("hh:mm", -3.857214768933151),+                                    ("until <time-of-day>", -4.2626798770413155),+                                    ("hour", -0.812692331209728), ("minute", -3.3463891451671604),+                                    ("after <time-of-day>", -3.857214768933151)],+                               n = 66},+                   koData =+                     ClassData{prior = -4.204692619390966, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.791759469228055),+                                    ("hour", -1.791759469228055)],+                               n = 1}}),+       ("fifteen",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.749199854809259, unseen = -3.0910424533583156,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.4350845252893227),+                                    ("hh:mmhh:mm", -1.4350845252893227)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.19105523676270922,+                               unseen = -3.951243718581427,+                               likelihoods =+                                 HashMap.fromList+                                   [("about <time-of-day>noon", -3.2386784521643803),+                                    ("relative minutes to|till|before <integer> (hour-of-day)<integer> (latent time-of-day)",+                                     -3.2386784521643803),+                                    ("minuteminute", -3.2386784521643803),+                                    ("<time-of-day> rano<time-of-day> rano", -3.2386784521643803),+                                    ("until <time-of-day>noon", -3.2386784521643803),+                                    ("hh:mmhh:mm", -3.2386784521643803),+                                    ("hourhour", -1.3668762752627892),+                                    ("minutehour", -1.9859154836690123),+                                    ("after <time-of-day>noon", -2.833213344056216),+                                    ("at <time-of-day>noon", -3.2386784521643803),+                                    ("<ordinal> (as hour)noon", -2.1400661634962708),+                                    ("<time-of-day> rano<integer> (latent time-of-day)",+                                     -3.2386784521643803),+                                    ("hh:mm<integer> (latent time-of-day)", -2.1400661634962708)],+                               n = 19}}),+       ("<hour-of-day> - <hour-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.3350010667323402),+                                    ("hh:mmhh:mm", -1.3350010667323402)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.2231435513142097, unseen = -3.784189633918261,+                               likelihoods =+                                 HashMap.fromList+                                   [("about <time-of-day>noon", -3.068052935133617),+                                    ("minuteminute", -3.068052935133617),+                                    ("<time-of-day> rano<time-of-day> rano", -3.068052935133617),+                                    ("until <time-of-day>noon", -3.068052935133617),+                                    ("hh:mmhh:mm", -3.068052935133617),+                                    ("hourhour", -0.9886113934537812),+                                    ("after <time-of-day>noon", -2.662587827025453),+                                    ("at <time-of-day>noon", -3.068052935133617),+                                    ("<ordinal> (as hour)noon", -1.9694406464655074),+                                    ("<integer> (latent time-of-day)noon", -2.662587827025453),+                                    ("<integer> (latent time-of-day)<ordinal> (as hour)",+                                     -2.662587827025453)],+                               n = 16}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.583997552432231),+                                    ("integer (numeric)day (grain)", -2.871679624884012),+                                    ("twoweek (grain)", -3.2771447329921766),+                                    ("twominute (grain)", -3.2771447329921766),+                                    ("second", -2.871679624884012),+                                    ("integer (numeric)second (grain)", -3.2771447329921766),+                                    ("twomonth (grain)", -3.2771447329921766),+                                    ("onehour (grain)", -3.2771447329921766),+                                    ("integer (numeric)year (grain)", -3.2771447329921766),+                                    ("day", -2.583997552432231), ("year", -2.871679624884012),+                                    ("integer (numeric)week (grain)", -2.871679624884012),+                                    ("twoday (grain)", -3.2771447329921766),+                                    ("hour", -2.871679624884012), ("month", -2.871679624884012),+                                    ("integer (numeric)minute (grain)", -3.2771447329921766),+                                    ("integer (numeric)month (grain)", -3.2771447329921766),+                                    ("minute", -2.871679624884012),+                                    ("twosecond (grain)", -3.2771447329921766),+                                    ("integer (numeric)hour (grain)", -3.2771447329921766),+                                    ("twoyear (grain)", -3.2771447329921766)],+                               n = 16},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 20},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 8}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.1431008436406733, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 13},+                   koData =+                     ClassData{prior = -2.0149030205422647,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("three",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4011973816621555,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 28},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.540445040947149),+                                    ("week (grain)named-month", -1.9459101490553135),+                                    ("day (grain)intersect", -1.9459101490553135),+                                    ("weekmonth", -1.540445040947149),+                                    ("day (grain)named-month", -1.9459101490553135),+                                    ("week (grain)intersect", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("14th ordinalnamed-month", -1.791759469228055),+                                    ("third ordinalnamed-month", -2.1972245773362196),+                                    ("ordinal (digits)named-month", -1.2809338454620642),+                                    ("month", -0.8109302162163288)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = -0.6190392084062235,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -0.7731898882334817,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("relative minutes to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)<integer> (latent time-of-day)",+                                     -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("10th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -1.4403615823901665,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -2.3353749158170367),+                                    ("<ordinal> (as hour)", -2.3353749158170367),+                                    ("afternoon", -2.0476928433652555),+                                    ("hour", -1.1314021114911006),+                                    ("<time-of-day> popo\322udniu/wieczorem/w nocy",+                                     -2.3353749158170367)],+                               n = 9},+                   koData =+                     ClassData{prior = -0.2702903297399117, unseen = -4.276666119016055,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> <part-of-day>", -3.164067588373206),+                                    ("<ordinal> (as hour)", -2.8763855159214247),+                                    ("intersect", -3.56953269648137),+                                    ("tomorrow", -2.653241964607215), ("day", -2.316769727986002),+                                    ("afternoon", -2.653241964607215),+                                    ("<day-of-month> (ordinal)", -3.164067588373206),+                                    ("noon", -2.1832383353614793), ("hour", -1.08462604669337),+                                    ("<datetime> - <datetime> (interval)", -3.164067588373206),+                                    ("<time-of-day> - <time-of-day> (interval)",+                                     -3.164067588373206),+                                    ("<hour-of-day> - <hour-of-day> (interval)",+                                     -3.164067588373206)],+                               n = 29}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = -0.12783337150988489,+                               unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -2.120263536200091, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("9th ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("first ordinal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day-after-tomorrow (single-word)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("<ordinal> (as hour)twenty", -1.3862943611198906),+                                    ("hour", -0.9808292530117262),+                                    ("<ordinal> (as hour)fifteen", -1.3862943611198906)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)integer (numeric)",+                                     -0.8754687373538999),+                                    ("hour", -0.8754687373538999)],+                               n = 4}}),+       ("23rd ordinal no space",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -0.6286086594223742,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -3.044522437723423),+                                    ("season", -2.128231705849268),+                                    ("evening|night", -3.044522437723423),+                                    ("day", -1.252762968495368), ("named-day", -1.6582280766035324),+                                    ("hour", -1.9459101490553135),+                                    ("week-end", -2.3513752571634776)],+                               n = 16},+                   koData =+                     ClassData{prior = -0.7621400520468967,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -2.9444389791664407),+                                    ("evening|night", -2.9444389791664407),+                                    ("named-month", -1.2396908869280152),+                                    ("day", -2.538973871058276), ("hour", -2.538973871058276),+                                    ("month", -1.2396908869280152),+                                    ("<named-month> <day-of-month> (non ordinal)",+                                     -2.538973871058276)],+                               n = 14}}),+       ("<named-month> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthfirst ordinal", -1.791759469228055),+                                    ("named-month15th ordinal", -1.791759469228055),+                                    ("month", -0.8754687373538999),+                                    ("named-monthordinal (digits)", -1.3862943611198906)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/PT.hs view
@@ -0,0 +1,1279 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.PT (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<cycle> (que vem)",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("semana (grain)", -1.540445040947149),+                                    ("mes (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135),+                                    ("ano (grain)", -1.9459101490553135),+                                    ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("semana (grain)", -1.791759469228055),+                                    ("mes (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055),+                                    ("ano (grain)", -1.791759469228055),+                                    ("month", -1.791759469228055)],+                               n = 3}}),+       ("midnight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> da tarde",+        Classifier{okData =+                     ClassData{prior = -0.24686007793152578, unseen = -4.0943445622221,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> and half", -2.468099531471619),+                                    ("time-of-day (latent)", -2.9789251552376097),+                                    ("<hour-of-day> and <relative minutes>", -2.1316272948504063),+                                    ("hour", -2.468099531471619),+                                    ("<hour-of-day> and quinze", -2.468099531471619),+                                    ("minute", -0.9864949905474035),+                                    ("\224s <time-of-day>", -1.7749523509116738)],+                               n = 25},+                   koData =+                     ClassData{prior = -1.5198257537444133,+                               unseen = -3.1780538303479458,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)", -1.3437347467010947),+                                    ("time-of-day (latent)", -2.03688192726104),+                                    ("year", -1.3437347467010947), ("hour", -2.03688192726104)],+                               n = 7}}),+       ("de <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.252762968495368),+                                    ("hour", -0.8472978603872037),+                                    ("\224s <time-of-day>", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.6427163269330534, unseen = -4.143134726391533,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 61},+                   koData =+                     ClassData{prior = -0.7462570058738938, unseen = -4.04305126783455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 55}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh(:|.|h)mm (time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month|named-day> past",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("proximo <cycle> ",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("semana (grain)", -1.540445040947149),+                                    ("mes (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135),+                                    ("ano (grain)", -1.9459101490553135),+                                    ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("semana (grain)", -1.791759469228055),+                                    ("mes (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055),+                                    ("ano (grain)", -1.791759469228055),+                                    ("month", -1.791759469228055)],+                               n = 3}}),+       ("dd[/-]mm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by `da` or `de`",+        Classifier{okData =+                     ClassData{prior = -0.6443570163905132, unseen = -4.31748811353631,+                               likelihoods =+                                 HashMap.fromList+                                   [("day of month (1st)named-month", -3.20545280453606),+                                    ("daymonth", -3.20545280453606),+                                    ("<day-of-month> de <named-month>two time tokens separated by \",\"2",+                                     -3.6109179126442243),+                                    ("<day-of-month> de <named-month>intersect",+                                     -3.6109179126442243),+                                    ("<day-of-month> de <named-month>two time tokens separated by \",\"",+                                     -3.6109179126442243),+                                    ("dayday", -2.917770732084279),+                                    ("dayyear", -1.6650077635889111),+                                    ("named-dayproximo <cycle> ", -3.6109179126442243),+                                    ("dd-dd <month>(interval)year", -3.6109179126442243),+                                    ("named-day<cycle> (que vem)", -3.6109179126442243),+                                    ("two time tokens separated by \",\"2year", -3.20545280453606),+                                    ("intersectyear", -3.6109179126442243),+                                    ("<day-of-month> de <named-month>year", -2.2246235515243336),+                                    ("two time tokens separated by \",\"year", -3.20545280453606),+                                    ("dayweek", -2.917770732084279),+                                    ("named-day<cycle> passado", -3.6109179126442243)],+                               n = 21},+                   koData =+                     ClassData{prior = -0.7444404749474959,+                               unseen = -4.2626798770413155,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> <integer> (as relative minutes)intersect",+                                     -3.5553480614894135),+                                    ("monthday", -2.8622008809294686),+                                    ("monthyear", -2.05127066471314),+                                    ("hourmonth", -3.1498829533812494),+                                    ("monthmonth", -3.5553480614894135),+                                    ("dayyear", -3.5553480614894135),+                                    ("minutemonth", -2.8622008809294686),+                                    ("named-monthyear", -2.05127066471314),+                                    ("de <datetime> - <datetime> (interval)named-month",+                                     -3.5553480614894135),+                                    ("\224s <time-of-day>named-month", -3.1498829533812494),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -3.5553480614894135),+                                    ("<day-of-month> de <named-month>year", -3.5553480614894135),+                                    ("intersect by `da` or `de`year", -3.5553480614894135),+                                    ("named-monthtwo time tokens separated by \",\"2",+                                     -3.5553480614894135),+                                    ("named-monthintersect", -3.5553480614894135),+                                    ("<hour-of-day> <integer> (as relative minutes)intersect by `da` or `de`",+                                     -3.5553480614894135),+                                    ("minuteyear", -3.5553480614894135),+                                    ("named-monthtwo time tokens separated by \",\"",+                                     -3.5553480614894135)],+                               n = 19}}),+       ("<hour-of-day> and half",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.4816045409242156),+                                    ("noon", -2.3978952727983707), ("hour", -0.7884573603642702),+                                    ("\224s <time-of-day>", -1.4816045409242156)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("semana (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two time tokens separated by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersectnamed-day", -2.772588722239781),+                                    ("intersect by `da` or `de`named-day", -2.772588722239781),+                                    ("dayday", -1.1631508098056809),+                                    ("de <year>named-day", -2.772588722239781),+                                    ("named-dayintersect", -2.367123614131617),+                                    ("named-dayintersect by `da` or `de`", -2.367123614131617),+                                    ("yearnamed-day", -2.772588722239781),+                                    ("named-day<day-of-month> de <named-month>",+                                     -2.0794415416798357),+                                    ("yearday", -2.367123614131617)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.8718021769015913, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.540445040947149),+                                    ("intersectnamed-day", -1.9459101490553135),+                                    ("intersect by `da` or `de`named-day", -1.9459101490553135)],+                               n = 2}}),+       ("ordinals (primeiro..10)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.4657359027997265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 30}}),+       ("<day-of-month> de <named-month>",+        Classifier{okData =+                     ClassData{prior = -7.410797215372185e-2,+                               unseen = -4.02535169073515,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..15)named-month", -1.927891643552635),+                                    ("integer (numeric)named-month", -1.0116009116784799),+                                    ("month", -0.7114963192281418)],+                               n = 26},+                   koData =+                     ClassData{prior = -2.639057329615259, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.8472978603872037),+                                    ("month", -0.8472978603872037)],+                               n = 2}}),+       ("<time-of-day> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.33270575382573614,+                               unseen = -4.584967478670572,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> and quinzeafternoon", -2.9652730660692823),+                                    ("<day-of-month> de <named-month>morning", -3.8815637979434374),+                                    ("dayhour", -3.4760986898352733),+                                    ("\224s <time-of-day>morning", -3.188416617383492),+                                    ("hourhour", -1.8021222562636017),+                                    ("<hour-of-day> and halfafternoon", -2.9652730660692823),+                                    ("minutehour", -1.483668525145067),+                                    ("time-of-day (latent)morning", -3.188416617383492),+                                    ("time-of-day (latent)evening", -3.4760986898352733),+                                    ("\224s <time-of-day>afternoon", -2.2721258855093374),+                                    ("dia <day-of-month> de <named-month>morning",+                                     -3.8815637979434374),+                                    ("time-of-day (latent)afternoon", -3.4760986898352733),+                                    ("<hour-of-day> and <relative minutes>afternoon",+                                     -2.62880082944807),+                                    ("intersectmorning", -3.8815637979434374),+                                    ("\224s <time-of-day>evening", -3.4760986898352733)],+                               n = 38},+                   koData =+                     ClassData{prior = -1.262241712449912, unseen = -3.951243718581427,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -1.4469189829363254),+                                    ("monthhour", -3.2386784521643803),+                                    ("hourhour", -2.5455312716044354),+                                    ("time-of-day (latent)morning", -3.2386784521643803),+                                    ("year (latent)afternoon", -2.1400661634962708),+                                    ("named-monthmorning", -3.2386784521643803),+                                    ("year (latent)evening", -2.833213344056216),+                                    ("time-of-day (latent)afternoon", -2.833213344056216),+                                    ("year (latent)morning", -2.322387720290225)],+                               n = 15}}),+       ("de <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.791759469228055),+                                    ("monthyear", -1.791759469228055),+                                    ("monthhour", -1.791759469228055),+                                    ("named-monthyear (latent)", -1.791759469228055),+                                    ("named-monthtime-of-day (latent)", -1.791759469228055),+                                    ("named-month<day-of-month> de <named-month>",+                                     -1.791759469228055)],+                               n = 3}}),+       ("<time-of-day> horas",+        Classifier{okData =+                     ClassData{prior = -0.7731898882334817,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.5040773967762742),+                                    ("hour", -0.9444616088408514),+                                    ("depois das <time-of-day>", -1.791759469228055),+                                    ("\224s <time-of-day>", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.6190392084062235, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.2039728043259361),+                                    ("<hour-of-day> and <relative minutes>", -2.3025850929940455),+                                    ("hour", -1.0498221244986778), ("minute", -2.3025850929940455),+                                    ("\224s <time-of-day>", -2.3025850929940455)],+                               n = 7}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -5.062595033026967,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> de <named-month>in the <part-of-day>",+                                     -3.9576335166801986),+                                    ("dayhour", -2.4171884757330493),+                                    ("<day-of-month> de <named-month>two time tokens separated by \",\"2",+                                     -4.363098624788362),+                                    ("nowquinze para as <hour-of-day> (as relative minutes)",+                                     -4.363098624788362),+                                    ("intersectnamed-day", -4.363098624788362),+                                    ("now\224s <time-of-day>", -3.9576335166801986),+                                    ("<day-of-month> de <named-month>intersect",+                                     -4.363098624788362),+                                    ("now<hour-of-day> and 3/4", -4.363098624788362),+                                    ("intersect by `da` or `de`named-day", -4.363098624788362),+                                    ("<day-of-month> de <named-month>two time tokens separated by \",\"",+                                     -4.363098624788362),+                                    ("dayday", -2.8590212280120886),+                                    ("hourhour", -4.363098624788362),+                                    ("named-day\224s <time-of-day>", -4.363098624788362),+                                    ("dayyear", -2.348195604246098),+                                    ("minutehour", -3.1103356562929947),+                                    ("<hour-of-day> and quinzein the <part-of-day>",+                                     -3.9576335166801986),+                                    ("de <year>named-day", -4.363098624788362),+                                    ("now<hour-of-day> and <relative minutes>", -4.363098624788362),+                                    ("named-dayin the <part-of-day>", -4.363098624788362),+                                    ("tomorrow<time-of-day> horas", -3.9576335166801986),+                                    ("now<integer> para as <hour-of-day> (as relative minutes)",+                                     -4.363098624788362),+                                    ("\224s <time-of-day>in the <part-of-day>",+                                     -3.6699514442284173),+                                    ("named-dayintersect", -4.363098624788362),+                                    ("named-dayamanh\227 pela <part-of-day>", -4.363098624788362),+                                    ("dayminute", -3.1103356562929947),+                                    ("named-dayintersect by `da` or `de`", -4.363098624788362),+                                    ("yearnamed-day", -4.363098624788362),+                                    ("dd-dd <month>(interval)de <year>", -4.363098624788362),+                                    ("named-day<day-of-month> de <named-month>",+                                     -4.363098624788362),+                                    ("named-day<time-of-day> <part-of-day>", -4.363098624788362),+                                    ("dia <day-of-month> de <named-month>in the <part-of-day>",+                                     -3.9576335166801986),+                                    ("yearday", -3.9576335166801986),+                                    ("named-day<dim time> da manha", -4.363098624788362),+                                    ("two time tokens separated by \",\"de <year>",+                                     -3.9576335166801986),+                                    ("dd[/-]mmyear", -4.363098624788362),+                                    ("<day-of-month> de <named-month>de <year>",+                                     -2.976804263668472),+                                    ("tomorrowdepois das <time-of-day>", -3.9576335166801986),+                                    ("<hour-of-day> and <relative minutes>in the <part-of-day>",+                                     -3.9576335166801986),+                                    ("two time tokens separated by \",\"2de <year>",+                                     -3.9576335166801986),+                                    ("intersectde <year>", -4.363098624788362)],+                               n = 50},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -4.68213122712422,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -3.979681653901961),+                                    ("dayhour", -3.5742165457937967),+                                    ("monthday", -2.8810693652338513),+                                    ("named-month\224s <time-of-day>", -3.979681653901961),+                                    ("monthyear", -2.4756042571256867),+                                    ("intersectnamed-day", -3.979681653901961),+                                    ("now\224s <time-of-day>", -3.5742165457937967),+                                    ("<time-of-day> am|pm<day-of-month> de <named-month>",+                                     -3.979681653901961),+                                    ("intersect by `da` or `de`named-day", -3.979681653901961),+                                    ("monthhour", -3.2865344733420154),+                                    ("dayyear", -3.979681653901961),+                                    ("now<hour-of-day> and <relative minutes>", -3.979681653901961),+                                    ("daysecond", -3.979681653901961),+                                    ("named-dayright now", -3.979681653901961),+                                    ("dayminute", -3.5742165457937967),+                                    ("named-monthde <year>", -2.4756042571256867),+                                    ("named-monthin the <part-of-day>", -3.5742165457937967),+                                    ("named-monthtwo time tokens separated by \",\"2",+                                     -3.979681653901961),+                                    ("intersect by `da` or `de`de <year>", -3.979681653901961),+                                    ("named-monthintersect", -3.979681653901961),+                                    ("<day-of-month> de <named-month>\224s <time-of-day>",+                                     -3.979681653901961),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -3.979681653901961),+                                    ("<day-of-month> de <named-month>de <year>",+                                     -3.979681653901961),+                                    ("minuteyear", -3.5742165457937967),+                                    ("named-monthtwo time tokens separated by \",\"",+                                     -3.979681653901961)],+                               n = 25}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minutos (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("two time tokens separated by \",\"2",+        Classifier{okData =+                     ClassData{prior = -0.1670540846631662,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersectnamed-day", -2.772588722239781),+                                    ("intersect by `da` or `de`named-day", -2.772588722239781),+                                    ("dayday", -1.1631508098056809),+                                    ("de <year>named-day", -2.772588722239781),+                                    ("named-dayintersect", -2.367123614131617),+                                    ("named-dayintersect by `da` or `de`", -2.367123614131617),+                                    ("yearnamed-day", -2.772588722239781),+                                    ("named-day<day-of-month> de <named-month>",+                                     -2.0794415416798357),+                                    ("yearday", -2.367123614131617)],+                               n = 11},+                   koData =+                     ClassData{prior = -1.8718021769015913, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.540445040947149),+                                    ("intersectnamed-day", -1.9459101490553135),+                                    ("intersect by `da` or `de`named-day", -1.9459101490553135)],+                               n = 2}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.3217558399823195),+                                    ("number (0..15)", -0.5108256237659907),+                                    ("number (20..90)", -2.0149030205422647)],+                               n = 12}}),+       ("n[ao] <date>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("dia <day-of-month> (non ordinal)", -1.252762968495368),+                                    ("day", -0.8472978603872037),+                                    ("named-day", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("amanh\227 pela <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.3184537311185346,+                               unseen = -4.6443908991413725,+                               likelihoods =+                                 HashMap.fromList+                                   [("<hour-of-day> and quinzeafternoon", -3.0252910757955354),+                                    ("<day-of-month> de <named-month>morning", -3.9415818076696905),+                                    ("dayhour", -3.0252910757955354),+                                    ("\224s <time-of-day>morning", -3.248434627109745),+                                    ("hourhour", -1.8621402659898547),+                                    ("<hour-of-day> and halfafternoon", -3.0252910757955354),+                                    ("minutehour", -1.54368653487132),+                                    ("tomorrowevening", -3.9415818076696905),+                                    ("time-of-day (latent)morning", -3.248434627109745),+                                    ("time-of-day (latent)evening", -3.536116699561526),+                                    ("\224s <time-of-day>afternoon", -2.33214389523559),+                                    ("dia <day-of-month> de <named-month>morning",+                                     -3.9415818076696905),+                                    ("yesterdayevening", -3.9415818076696905),+                                    ("time-of-day (latent)afternoon", -3.536116699561526),+                                    ("<hour-of-day> and <relative minutes>afternoon",+                                     -2.6888188391743224),+                                    ("intersectmorning", -3.9415818076696905),+                                    ("\224s <time-of-day>evening", -3.536116699561526)],+                               n = 40},+                   koData =+                     ClassData{prior = -1.2992829841302609,+                               unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("yearhour", -1.4853852637641216),+                                    ("monthhour", -3.2771447329921766),+                                    ("hourhour", -2.583997552432231),+                                    ("time-of-day (latent)morning", -3.2771447329921766),+                                    ("year (latent)afternoon", -2.178532444324067),+                                    ("named-monthmorning", -3.2771447329921766),+                                    ("year (latent)evening", -2.871679624884012),+                                    ("time-of-day (latent)afternoon", -2.871679624884012),+                                    ("year (latent)morning", -2.3608540011180215)],+                               n = 15}}),+       ("dentro de <duration>",+        Classifier{okData =+                     ClassData{prior = -2.772588722239781, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> <unit-of-duration>", -1.6094379124341003),+                                    ("hour", -1.6094379124341003)],+                               n = 1},+                   koData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9444389791664407), ("second", -2.9444389791664407),+                                    ("day", -2.538973871058276), ("year", -2.538973871058276),+                                    ("<integer> <unit-of-duration>", -0.8649974374866046),+                                    ("hour", -2.2512917986064953), ("month", -2.9444389791664407),+                                    ("minute", -1.845826690498331)],+                               n = 15}}),+       ("dia <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4339872044851463,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 29},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dia <day-of-month> de <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("evening", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (0..15)",+        Classifier{okData =+                     ClassData{prior = -1.9048194970694474e-2,+                               unseen = -3.9889840465642745,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 52},+                   koData =+                     ClassData{prior = -3.970291913552122, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("antes das <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight", -1.2992829841302609),+                                    ("noon", -1.2992829841302609), ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("dd-dd <month>(interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<cycle> passado",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("semana (grain)", -1.540445040947149),+                                    ("mes (grain)", -1.9459101490553135),+                                    ("year", -1.9459101490553135),+                                    ("ano (grain)", -1.9459101490553135),+                                    ("month", -1.9459101490553135)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = -0.3364722366212129,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -1.252762968495368, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("mes (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> para as <hour-of-day> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)noon", -1.7047480922384253),+                                    ("hour", -0.7884573603642702),+                                    ("number (0..15)noon", -1.0116009116784799)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> da manha",+        Classifier{okData =+                     ClassData{prior = -0.2006706954621511, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month> de <named-month>", -2.6026896854443837),+                                    ("intersect", -2.6026896854443837),+                                    ("dia <day-of-month> de <named-month>", -2.6026896854443837),+                                    ("day", -2.1972245773362196),+                                    ("time-of-day (latent)", -1.9095425048844386),+                                    ("hour", -1.2163953243244932),+                                    ("\224s <time-of-day>", -1.9095425048844386)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.7047480922384253, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.8718021769015913),+                                    ("time-of-day (latent)", -1.8718021769015913),+                                    ("hour", -1.8718021769015913), ("month", -1.8718021769015913)],+                               n = 2}}),+       ("em <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9444389791664407), ("second", -2.9444389791664407),+                                    ("day", -2.538973871058276), ("year", -2.538973871058276),+                                    ("<integer> <unit-of-duration>", -0.8649974374866046),+                                    ("hour", -2.2512917986064953), ("month", -2.9444389791664407),+                                    ("minute", -1.845826690498331)],+                               n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("passados n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)dia (grain)", -1.791759469228055),+                                    ("integer (numeric)mes (grain)", -1.791759469228055),+                                    ("integer (numeric)ano (grain)", -1.791759469228055),+                                    ("day", -1.791759469228055), ("year", -1.791759469228055),+                                    ("month", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> and 3/4",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.2992829841302609),+                                    ("hour", -0.7884573603642702),+                                    ("\224s <time-of-day>", -1.2992829841302609)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.43286408229627876,+                               unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.0986122886681098),+                                    ("number (0..15)", -0.46262352194811296)],+                               n = 24},+                   koData =+                     ClassData{prior = -1.0459685551826876, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.8266785731844679),+                                    ("number (0..15)", -0.8266785731844679),+                                    ("number (20..90)", -2.0794415416798357)],+                               n = 13}}),+       ("<hour-of-day> and <relative minutes>",+        Classifier{okData =+                     ClassData{prior = -0.2719337154836418, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224s <time-of-day>number (0..15)", -2.3025850929940455),+                                    ("time-of-day (latent)number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+                                     -2.5902671654458267),+                                    ("\224s <time-of-day>number (20..90)", -2.5902671654458267),+                                    ("\224s <time-of-day>number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+                                     -2.5902671654458267),+                                    ("time-of-day (latent)number (0..15)", -2.0794415416798357),+                                    ("hour", -0.8556661100577202),+                                    ("time-of-day (latent)number (20..90)", -2.5902671654458267),+                                    ("noonnumber (0..15)", -2.995732273553991)],+                               n = 16},+                   koData =+                     ClassData{prior = -1.4350845252893227,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("\224s <time-of-day>number (20..90)", -1.791759469228055),+                                    ("time-of-day (latent)number (0..15)", -2.1972245773362196),+                                    ("hour", -1.0986122886681098),+                                    ("time-of-day (latent)number (20..90)", -1.791759469228055)],+                               n = 5}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 9},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 6}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.6443570163905132, unseen = -4.174387269895637,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.772588722239781),+                                    ("number (0..15)ano (grain)", -3.0602707946915624),+                                    ("integer (numeric)hora (grain)", -3.4657359027997265),+                                    ("integer (numeric)dia (grain)", -3.4657359027997265),+                                    ("number (0..15)segundo (grain)", -3.4657359027997265),+                                    ("second", -3.4657359027997265),+                                    ("integer (numeric)ano (grain)", -3.4657359027997265),+                                    ("integer (numeric)minutos (grain)", -2.772588722239781),+                                    ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)hora (grain)",+                                     -3.4657359027997265),+                                    ("day", -3.0602707946915624), ("year", -2.772588722239781),+                                    ("number (0..15)mes (grain)", -3.0602707946915624),+                                    ("number (0..15)hora (grain)", -2.772588722239781),+                                    ("hour", -2.367123614131617), ("month", -3.0602707946915624),+                                    ("number (0..15)dia (grain)", -3.4657359027997265),+                                    ("number (0..15)minutos (grain)", -3.0602707946915624),+                                    ("minute", -2.367123614131617),+                                    ("number (0..15)semana (grain)", -2.772588722239781)],+                               n = 21},+                   koData =+                     ClassData{prior = -0.7444404749474959, unseen = -4.110873864173311,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.995732273553991),+                                    ("number (0..15)ano (grain)", -3.4011973816621555),+                                    ("integer (numeric)hora (grain)", -2.70805020110221),+                                    ("integer (numeric)dia (grain)", -2.995732273553991),+                                    ("integer (numeric)mes (grain)", -3.4011973816621555),+                                    ("second", -2.995732273553991),+                                    ("integer (numeric)semana (grain)", -3.4011973816621555),+                                    ("integer (numeric)ano (grain)", -2.995732273553991),+                                    ("integer (numeric)minutos (grain)", -2.995732273553991),+                                    ("day", -2.995732273553991),+                                    ("integer (numeric)segundo (grain)", -2.995732273553991),+                                    ("year", -2.70805020110221),+                                    ("number (0..15)mes (grain)", -2.995732273553991),+                                    ("number (0..15)hora (grain)", -2.995732273553991),+                                    ("hour", -2.3025850929940455), ("month", -2.70805020110221),+                                    ("minute", -2.995732273553991),+                                    ("number (0..15)semana (grain)", -3.4011973816621555)],+                               n = 19}}),+       ("proximas n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("number (0..15)ano (grain)", -2.4849066497880004),+                                    ("integer (numeric)hora (grain)", -2.4849066497880004),+                                    ("integer (numeric)dia (grain)", -2.4849066497880004),+                                    ("second", -2.4849066497880004),+                                    ("integer (numeric)minutos (grain)", -2.4849066497880004),+                                    ("day", -2.4849066497880004),+                                    ("integer (numeric)segundo (grain)", -2.4849066497880004),+                                    ("year", -2.4849066497880004),+                                    ("number (0..15)mes (grain)", -2.4849066497880004),+                                    ("hour", -2.4849066497880004), ("month", -2.4849066497880004),+                                    ("minute", -2.4849066497880004)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.252762968495368),+                                    ("hour", -0.8472978603872037),+                                    ("\224s <time-of-day>", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -1.791759469228055,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 1}}),+       ("n proximas <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("integer (numeric)mes (grain)", -1.791759469228055),+                                    ("integer (numeric)semana (grain)", -1.791759469228055),+                                    ("integer (numeric)ano (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055), ("month", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("vespera de ano novo",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.189654742026425,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 64},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number (21..29 31..39 41..49 51..59 61..69 71..79 81..89 91..99)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList [("number (20..90)number (0..15)", 0.0)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day of month (1st)",+        Classifier{okData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("ano (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("este <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("semana (grain)", -1.6094379124341003),+                                    ("year", -1.6094379124341003),+                                    ("ano (grain)", -1.6094379124341003)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.0986122886681098),+                                    ("dia (grain)", -1.0986122886681098)],+                               n = 3}}),+       ("<named-month|named-day> next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<part-of-day> dessa semana",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ano novo",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("dd[/-.]mm[/-.]yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n <cycle> (proximo|que vem)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055),+                                    ("integer (numeric)semana (grain)", -1.791759469228055),+                                    ("integer (numeric)ano (grain)", -1.791759469228055),+                                    ("year", -1.791759469228055),+                                    ("number (0..15)mes (grain)", -1.791759469228055),+                                    ("month", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> and quinze",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.3862943611198906),+                                    ("noon", -2.3025850929940455), ("hour", -0.7985076962177716),+                                    ("\224s <time-of-day>", -1.6094379124341003)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("depois das <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> horas", -1.6739764335716716),+                                    ("time-of-day (latent)", -1.6739764335716716),+                                    ("noon", -1.6739764335716716), ("hour", -0.8266785731844679)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.9459101490553135),+                                    ("dayday", -1.9459101490553135),+                                    ("hh(:|.|h)mm (time-of-day)hh(:|.|h)mm (time-of-day)",+                                     -1.9459101490553135),+                                    ("<day-of-month> de <named-month><day-of-month> de <named-month>",+                                     -1.9459101490553135)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -2.0794415416798357),+                                    ("dayyear", -2.0794415416798357),+                                    ("named-month<day-of-month> de <named-month>",+                                     -2.0794415416798357),+                                    ("dd[/-]mmyear", -2.0794415416798357),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -2.0794415416798357),+                                    ("minuteyear", -2.0794415416798357)],+                               n = 3}}),+       ("segundo (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dia (grain)",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("in the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("afternoon", -1.8718021769015913),+                                    ("hour", -0.7731898882334817),+                                    ("morning", -0.9555114450274363)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("natal",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hora (grain)",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("right now",+        Classifier{okData =+                     ClassData{prior = -0.1823215567939546,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -1.791759469228055, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quinze para as <hour-of-day> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -0.6931471805599453), ("hour", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("\224s <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.16507975035944858,+                               unseen = -4.499809670330265,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> timezone", -3.7954891891721947),+                                    ("<hour-of-day> and half", -2.8791984572980396),+                                    ("<time-of-day> horas", -3.7954891891721947),+                                    ("<hour-of-day> and 3/4", -3.39002408106403),+                                    ("time-of-day (latent)", -1.4441139320087168),+                                    ("<hour-of-day> and <relative minutes>", -2.409194828052304),+                                    ("<time-of-day> am|pm", -3.7954891891721947),+                                    ("hour", -1.3105825393841943),+                                    ("<hour-of-day> and quinze", -3.1023420086122493),+                                    ("minute", -1.6554230256759237)],+                               n = 39},+                   koData =+                     ClassData{prior = -1.8827312474337816, unseen = -3.258096538021482,+                               likelihoods =+                                 HashMap.fromList+                                   [("midnight", -2.5257286443082556),+                                    ("<time-of-day> horas", -2.5257286443082556),+                                    ("time-of-day (latent)", -1.8325814637483102),+                                    ("<hour-of-day> and <relative minutes>", -2.120263536200091),+                                    ("hour", -1.4271163556401458), ("minute", -2.120263536200091)],+                               n = 7}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2}}),+       ("fazem <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003), ("year", -2.0149030205422647),+                                    ("<integer> <unit-of-duration>", -0.916290731874155),+                                    ("hour", -2.0149030205422647), ("month", -2.0149030205422647)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("n <cycle> atras",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.791759469228055), ("second", -1.791759469228055),+                                    ("integer (numeric)minutos (grain)", -1.791759469228055),+                                    ("integer (numeric)segundo (grain)", -1.791759469228055),+                                    ("minute", -1.791759469228055),+                                    ("number (0..15)semana (grain)", -1.791759469228055)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -2.1102132003465894),+                                    ("dia <day-of-month> (non ordinal)", -2.1102132003465894),+                                    ("day", -1.1939224684724346),+                                    ("named-day", -2.1102132003465894),+                                    ("hour", -1.8870696490323797), ("evening", -2.3978952727983707),+                                    ("week-end", -2.3978952727983707)],+                               n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/RO.hs view
@@ -0,0 +1,265 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.RO (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("acum",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.13353139262452263,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.9924301646902063),+                                    ("dayday", -1.2992829841302609),+                                    ("<named-day> <day-of-month> (number)named-month",+                                     -1.9924301646902063),+                                    ("absorption of , after named day<day-of-month>(number) <named-month>",+                                     -1.9924301646902063),+                                    ("absorption of , after named day<day-of-month> (non ordinal) <named-month>",+                                     -1.9924301646902063),+                                    ("named-daythe <day-of-month> (number)", -2.3978952727983707)],+                               n = 7},+                   koData =+                     ClassData{prior = -2.0794415416798357,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month<hour-of-day> <integer> (as relative minutes)",+                                     -1.6094379124341003),+                                    ("monthminute", -1.6094379124341003)],+                               n = 1}}),+       ("<named-day> <day-of-month> (number)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayinteger (numeric)", -1.2992829841302609),+                                    ("day", -0.7884573603642702),+                                    ("absorption of , after named dayinteger (numeric)",+                                     -1.2992829841302609)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with - or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("craciun",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the <day-of-month> (number)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 1}}),+       ("ieri",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.7884573603642702),+                                    ("named-day<day-of-month>(number) <named-month>",+                                     -1.2992829841302609),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -1.2992829841302609)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("azi",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1780538303479458,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-day> pe <day-of-month> (number)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-dayinteger (numeric)", -0.6931471805599453),+                                    ("day", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (0..10)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> (aceasta|acesta|[a\259]sta)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -1.0116009116784799),+                                    ("integer (0..10)named-month", -1.7047480922384253),+                                    ("month", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("maine",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1}}),+       ("<day-of-month>(number) <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -1.0116009116784799),+                                    ("integer (0..10)named-month", -1.7047480922384253),+                                    ("month", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/RU.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.RU (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/SV.hs view
@@ -0,0 +1,1596 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.SV (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.2039728043259361),+                                    ("hh:mm", -1.6094379124341003), ("hour", -1.6094379124341003),+                                    ("minute", -1.2039728043259361)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.7672551527136672, unseen = -4.882801922586371,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 130},+                   koData =+                     ClassData{prior = -0.6241543090729939,+                               unseen = -5.0238805208462765,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 150}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("integer (20..90)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -0.9555114450274363),+                                    ("tomorrowevening", -1.8718021769015913),+                                    ("named-daymorning", -1.8718021769015913),+                                    ("tomorrowlunch", -1.8718021769015913),+                                    ("yesterdayevening", -1.8718021769015913)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("couple, a pair",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd/mm",+        Classifier{okData =+                     ClassData{prior = -0.2231435513142097,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("at <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2607262624632527, unseen = -4.624972813284271,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time> timezone", -3.5165082281731497),+                                    ("time-of-day (latent)", -1.2139231351791042),+                                    ("relative minutes after|past <integer> (hour-of-day)",+                                     -3.5165082281731497),+                                    ("hh:mm", -2.0501711593797225),+                                    ("<time-of-day> sharp", -3.5165082281731497),+                                    ("hour", -1.149384614041533), ("minute", -1.7819071727850433)],+                               n = 47},+                   koData =+                     ClassData{prior = -1.4718165345580525, unseen = -3.58351893845611,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.8472978603872037),+                                    ("hour", -0.8472978603872037)],+                               n = 14}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("on <date>",+        Classifier{okData =+                     ClassData{prior = -0.45198512374305727,+                               unseen = -4.430816798843313,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -3.3202283191284883),+                                    ("the <day-of-month> (non ordinal)", -3.3202283191284883),+                                    ("<day-of-month>(ordinal) <named-month>", -2.339399066116762),+                                    ("day", -0.8634925463071842),+                                    ("the <day-of-month> (ordinal)", -3.3202283191284883),+                                    ("afternoon", -3.7256934272366524),+                                    ("named-day", -2.1162555148025524),+                                    ("<day-of-month> (ordinal)", -1.9339339580085977),+                                    ("hour", -3.7256934272366524),+                                    ("<day-of-month> (non ordinal) <named-month>",+                                     -3.7256934272366524)],+                               n = 35},+                   koData =+                     ClassData{prior = -1.0116009116784799,+                               unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("on <date>", -2.3608540011180215),+                                    ("year (latent)", -1.7730673362159024),+                                    ("time-of-day (latent)", -1.7730673362159024),+                                    ("year", -1.5723966407537513), ("hour", -1.5723966407537513)],+                               n = 20}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -0.2803019651541584, unseen = -3.58351893845611,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 34},+                   koData =+                     ClassData{prior = -1.4087672169719492,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11}}),+       ("between <time-of-day> and <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.9808292530117262),+                                    ("hh:mmhh:mm", -0.9808292530117262)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 2}}),+       ("between <datetime> and <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.252762968495368, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.2992829841302609),+                                    ("hh:mmhh:mm", -1.2992829841302609)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.3364722366212129, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mm<day-of-month> (ordinal)", -1.7346010553881064),+                                    ("hh:mmtime-of-day (latent)", -1.7346010553881064),+                                    ("minuteminute", -2.1400661634962708),+                                    ("minutehour", -1.7346010553881064),+                                    ("hh:mmintersect", -2.1400661634962708),+                                    ("minuteday", -1.7346010553881064)],+                               n = 5}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> more <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)minute (grain)", -1.252762968495368),+                                    ("integer (0..19)minute (grain)", -1.252762968495368),+                                    ("minute", -0.8472978603872037)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -0.11778303565638351,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8},+                   koData =+                     ClassData{prior = -2.1972245773362196,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("<ordinal> quarter",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.0986122886681098),+                                    ("quarter", -0.8109302162163288),+                                    ("ordinals (first..31st)quarter (grain)", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)quarter (grain)", -1.252762968495368),+                                    ("quarter", -0.8472978603872037),+                                    ("ordinals (first..31st)quarter (grain)", -1.252762968495368)],+                               n = 2}}),+       ("Last year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.4382549309311553, unseen = -6.003887067106539,+                               likelihoods =+                                 HashMap.fromList+                                   [("<datetime> - <datetime> (interval)on <date>",+                                     -4.209655408733095),+                                    ("<time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.209655408733095),+                                    ("hourday", -5.308267697401205),+                                    ("dayhour", -3.0569758987947098),+                                    ("daymonth", -2.956892440237727),+                                    ("monthyear", -3.29336467685894),+                                    ("intersecthh:mm", -4.9028025892930405),+                                    ("named-daylast <cycle>", -5.308267697401205),+                                    ("the <day-of-month> (ordinal)named-month",+                                     -3.9219733362813143),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -4.9028025892930405),+                                    ("last <day-of-week> of <time>year", -5.308267697401205),+                                    ("todayat <time-of-day>", -4.9028025892930405),+                                    ("dayday", -2.6341190479746763),+                                    ("dd/mmat <time-of-day>", -4.39197696552705),+                                    ("intersect by \",\"hh:mm", -3.804190300624931),+                                    ("named-day<named-month> <day-of-month> (ordinal)",+                                     -5.308267697401205),+                                    ("intersectnamed-month", -4.9028025892930405),+                                    ("dayyear", -3.362357548345891),+                                    ("named-daythis <time>", -4.209655408733095),+                                    ("tomorrow<time-of-day> sharp", -4.9028025892930405),+                                    ("<day-of-month>(ordinal) <named-month>year",+                                     -4.39197696552705),+                                    ("absorption of , after named day<day-of-month>(ordinal) <named-month>",+                                     -4.61512051684126),+                                    ("absorption of , after named day<named-month> <day-of-month> (ordinal)",+                                     -4.209655408733095),+                                    ("named-day<time> timezone", -4.61512051684126),+                                    ("named-monthyear", -3.29336467685894),+                                    ("absorption of , after named day<named-month> <day-of-month> (non ordinal)",+                                     -4.209655408733095),+                                    ("on <date>named-month", -3.9219733362813143),+                                    ("tomorrowuntil <time-of-day>", -4.9028025892930405),+                                    ("absorption of , after named day<day-of-month> (non ordinal) <named-month>",+                                     -4.61512051684126),+                                    ("after <time-of-day>at <time-of-day>", -4.9028025892930405),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -4.9028025892930405),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -5.308267697401205),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -5.308267697401205),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -4.9028025892930405),+                                    ("named-daynext <cycle>", -5.308267697401205),+                                    ("named-dayintersect", -4.9028025892930405),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.9028025892930405),+                                    ("tomorrowafter <time-of-day>", -4.9028025892930405),+                                    ("from <time-of-day> - <time-of-day> (interval)on <date>",+                                     -4.39197696552705),+                                    ("dayminute", -2.6692103677859462),+                                    ("from <datetime> - <datetime> (interval)on <date>",+                                     -4.61512051684126),+                                    ("<ordinal> <cycle> of <time>year", -4.9028025892930405),+                                    ("minuteday", -2.6341190479746763),+                                    ("absorption of , after named dayintersect",+                                     -4.9028025892930405),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -5.308267697401205),+                                    ("named-dayon <date>", -4.61512051684126),+                                    ("named-dayat <time-of-day>", -4.9028025892930405),+                                    ("yearhh:mm", -5.308267697401205),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -5.308267697401205),+                                    ("absorption of , after named dayintersect by \",\"",+                                     -4.39197696552705),+                                    ("dd/mmyear", -4.9028025892930405),+                                    ("at <time-of-day>on <date>", -5.308267697401205),+                                    ("between <time-of-day> and <time-of-day> (interval)on <date>",+                                     -5.308267697401205),+                                    ("between <datetime> and <datetime> (interval)on <date>",+                                     -5.308267697401205),+                                    ("dayweek", -4.055504728905837),+                                    ("intersect by \",\"<day-of-month>(ordinal) <named-month>",+                                     -4.9028025892930405),+                                    ("weekyear", -4.39197696552705),+                                    ("hh:mmtomorrow", -4.61512051684126),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -5.308267697401205),+                                    ("tomorrowat <time-of-day>", -4.055504728905837),+                                    ("named-daythis <cycle>", -4.61512051684126),+                                    ("named-daythe <day-of-month> (ordinal)", -5.308267697401205),+                                    ("at <time-of-day>tomorrow", -4.9028025892930405),+                                    ("last <cycle> of <time>year", -4.39197696552705),+                                    ("<day-of-month> (non ordinal) <named-month>year",+                                     -4.9028025892930405),+                                    ("yearminute", -5.308267697401205)],+                               n = 160},+                   koData =+                     ClassData{prior = -1.0360919316867756, unseen = -5.564520407322694,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -4.867534450455582),+                                    ("dayhour", -3.258096538021482),+                                    ("daymonth", -2.0343211063993665),+                                    ("monthday", -3.3634570536793085),+                                    ("monthyear", -3.951243718581427),+                                    ("intersect by \"of\", \"from\", \"'s\"year",+                                     -3.7689221617874726),+                                    ("hourmonth", -4.462069342347418),+                                    ("named-dayhh:mm", -4.867534450455582),+                                    ("dayday", -4.867534450455582),+                                    ("dd/mmat <time-of-day>", -3.951243718581427),+                                    ("intersectnamed-month", -4.462069342347418),+                                    ("dayyear", -3.481240089335692),+                                    ("named-daythis <time>", -2.921624301400269),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -4.462069342347418),+                                    ("minutemonth", -4.462069342347418),+                                    ("named-monthyear", -3.951243718581427),+                                    ("on <date>named-month", -4.462069342347418),+                                    ("absorption of , after named daynamed-month",+                                     -3.7689221617874726),+                                    ("named-dayfrom <datetime> - <datetime> (interval)",+                                     -3.7689221617874726),+                                    ("named-dayintersect", -4.462069342347418),+                                    ("named-month<day-of-month>(ordinal) <named-month>",+                                     -3.951243718581427),+                                    ("<hour-of-day> <integer> (as relative minutes)named-month",+                                     -4.462069342347418),+                                    ("named-dayfrom <time-of-day> - <time-of-day> (interval)",+                                     -4.867534450455582),+                                    ("yearmonth", -4.867534450455582),+                                    ("until <time-of-day>on <date>", -4.867534450455582),+                                    ("<named-month> <day-of-month> (ordinal)named-month",+                                     -3.951243718581427),+                                    ("dayminute", -3.258096538021482),+                                    ("minuteday", -3.3634570536793085),+                                    ("named-daybetween <time-of-day> and <time-of-day> (interval)",+                                     -4.867534450455582),+                                    ("named-dayon <date>", -4.462069342347418),+                                    ("named-dayat <time-of-day>", -3.951243718581427),+                                    ("hh:mmon <date>", -3.481240089335692),+                                    ("named-daybetween <datetime> and <datetime> (interval)",+                                     -4.462069342347418),+                                    ("<day-of-month>(ordinal) <named-month> yearnamed-month",+                                     -3.951243718581427),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -3.951243718581427),+                                    ("<named-month> <day-of-month> (non ordinal)named-month",+                                     -3.951243718581427),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -4.462069342347418),+                                    ("minuteyear", -4.462069342347418),+                                    ("yearminute", -4.462069342347418)],+                               n = 88}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)intersect",+                                     -1.7346010553881064),+                                    ("ordinals (first..31st)week (grain)named-month",+                                     -1.7346010553881064),+                                    ("weekmonth", -1.2237754316221157),+                                    ("ordinals (first..31st)day (grain)named-month",+                                     -1.7346010553881064)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -1.4816045409242156,+                               unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.824549292051046),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.740840023925201),+                                    ("hh:mmhh:mm", -1.824549292051046),+                                    ("hourhour", -2.740840023925201)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.2578291093020998, unseen = -4.02535169073515,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -3.3141860046725258),+                                    ("dayhour", -3.3141860046725258),+                                    ("yearhour", -3.3141860046725258),+                                    ("hh:mm<day-of-month> (ordinal)", -2.3978952727983707),+                                    ("time-of-day (latent)<day-of-month> (ordinal)",+                                     -3.3141860046725258),+                                    ("<day-of-month> (ordinal)time-of-day (latent)",+                                     -3.3141860046725258),+                                    ("hh:mmtime-of-day (latent)", -2.3978952727983707),+                                    ("minuteminute", -2.6210388241125804),+                                    ("yearyear", -3.3141860046725258),+                                    ("<day-of-month> (ordinal)<day-of-month> (ordinal)",+                                     -3.3141860046725258),+                                    ("dayday", -3.3141860046725258),+                                    ("year (latent)year (latent)", -3.3141860046725258),+                                    ("minutehour", -2.3978952727983707),+                                    ("hh:mmintersect", -2.6210388241125804),+                                    ("year (latent)time-of-day (latent)", -3.3141860046725258),+                                    ("minuteday", -2.3978952727983707),+                                    ("year (latent)<day-of-month> (ordinal)", -3.3141860046725258),+                                    ("yearday", -3.3141860046725258)],+                               n = 17}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6094379124341003),+                                    ("month (grain)", -2.3025850929940455),+                                    ("year (grain)", -2.3025850929940455),+                                    ("week (grain)", -1.6094379124341003),+                                    ("quarter", -2.3025850929940455), ("year", -2.3025850929940455),+                                    ("month", -2.3025850929940455),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("number.number hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("from <time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156,+                               unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -1.0986122886681098),+                                    ("time-of-day (latent)time-of-day (latent)",+                                     -2.1972245773362196),+                                    ("hh:mmhh:mm", -1.0986122886681098),+                                    ("hourhour", -2.1972245773362196)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.9808292530117262),+                                    ("minutehour", -0.9808292530117262)],+                               n = 5}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (latent)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.3746934494414107),+                                    ("integer (0..19)", -1.1631508098056809)],+                               n = 30}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<ordinal> quarter <year>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)quarter (grain)year",+                                     -1.252762968495368),+                                    ("quarteryear", -0.8472978603872037),+                                    ("ordinal (digits)quarter (grain)year", -1.252762968495368)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter to|till|before <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.0986122886681098),+                                    ("noon", -1.5040773967762742), ("hour", -0.8109302162163288)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7472144018302211),+                                    ("ordinals (first..31st)named-dayintersect",+                                     -0.9985288301111273),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -1.845826690498331)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.8472978603872037, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -0.7621400520468967),+                                    ("ordinals (first..31st)named-daynamed-month",+                                     -0.7621400520468967)],+                               n = 6}}),+       ("the <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinals (first..31st)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.174387269895637,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 63},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 25},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("this <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("morning", -0.6931471805599453)],+                               n = 1}}),+       ("<day-of-month>(ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.12921173148000623,+                               unseen = -4.127134385045092,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -2.501435951739211),+                                    ("ordinal (digits)named-month", -0.8527773261518292),+                                    ("month", -0.7096764825111559)],+                               n = 29},+                   koData =+                     ClassData{prior = -2.1102132003465894,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.7047480922384253),+                                    ("ordinal (digits)named-month", -1.0116009116784799),+                                    ("month", -0.7884573603642702)],+                               n = 4}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 23}}),+       ("in|during the <part-of-day>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("morning", -0.6931471805599453)],+                               n = 1}}),+       ("new year's eve",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 15},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> after next",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("half an hour",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2}}),+       ("the <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)", -1.1786549963416462),+                                    ("ordinal (digits)", -0.3677247801253174)],+                               n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<duration> from now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("second", -1.2039728043259361),+                                    ("<integer> <unit-of-duration>", -1.2039728043259361),+                                    ("a <unit-of-duration>", -1.6094379124341003),+                                    ("minute", -1.6094379124341003)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.3862943611198906),+                                    ("year (grain)", -1.8971199848858813),+                                    ("week (grain)", -1.3862943611198906),+                                    ("quarter", -2.3025850929940455), ("year", -1.8971199848858813),+                                    ("quarter (grain)", -2.3025850929940455)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 2}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -1.006804739414987, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -5.129329438755058e-2),+                                    ("integer (0..19)", -2.995732273553991)],+                               n = 38},+                   koData =+                     ClassData{prior = -0.4547361571149472, unseen = -4.23410650459726,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.24921579162398486),+                                    ("integer (0..19)", -1.5114575040738967)],+                               n = 66}}),+       ("year",+        Classifier{okData =+                     ClassData{prior = -0.14842000511827333,+                               unseen = -3.295836866004329,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 25},+                   koData =+                     ClassData{prior = -1.9810014688665833, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("last <day-of-week> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.0986122886681098),+                                    ("daymonth", -0.8109302162163288),+                                    ("named-dayintersect", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -0.6375773294051346, unseen = -4.59511985013459,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.639057329615259),+                                    ("integer (0..19)year (grain)", -3.891820298110627),+                                    ("integer (numeric)day (grain)", -2.793208009442517),+                                    ("couple, a pairhour (grain)", -3.891820298110627),+                                    ("integer (0..19)hour (grain)", -3.891820298110627),+                                    ("second", -3.1986731175506815),+                                    ("integer (numeric)second (grain)", -3.891820298110627),+                                    ("integer (numeric)year (grain)", -3.891820298110627),+                                    ("day", -2.187072205872201), ("year", -3.4863551900024623),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("integer (0..19)month (grain)", -3.891820298110627),+                                    ("integer (0..19)second (grain)", -3.4863551900024623),+                                    ("hour", -2.793208009442517), ("month", -3.4863551900024623),+                                    ("integer (numeric)minute (grain)", -2.793208009442517),+                                    ("integer (0..19)minute (grain)", -2.9755295662364714),+                                    ("integer (numeric)month (grain)", -3.891820298110627),+                                    ("minute", -2.2823823856765264),+                                    ("integer (numeric)hour (grain)", -3.1986731175506815),+                                    ("integer (0..19)day (grain)", -2.793208009442517),+                                    ("integer (0..19)week (grain)", -3.1986731175506815)],+                               n = 37},+                   koData =+                     ClassData{prior = -0.7519876805828788, unseen = -4.51085950651685,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.70805020110221),+                                    ("integer (0..19)year (grain)", -3.4011973816621555),+                                    ("integer (numeric)day (grain)", -3.1135153092103742),+                                    ("integer (numeric)quarter (grain)", -3.8066624897703196),+                                    ("integer (0..19)hour (grain)", -3.8066624897703196),+                                    ("second", -2.890371757896165),+                                    ("integer (numeric)second (grain)", -3.4011973816621555),+                                    ("integer (numeric)year (grain)", -3.1135153092103742),+                                    ("day", -2.70805020110221), ("quarter", -3.8066624897703196),+                                    ("year", -2.70805020110221),+                                    ("integer (numeric)week (grain)", -3.4011973816621555),+                                    ("integer (0..19)month (grain)", -3.1135153092103742),+                                    ("integer (0..19)second (grain)", -3.4011973816621555),+                                    ("hour", -2.890371757896165), ("month", -2.70805020110221),+                                    ("integer (numeric)minute (grain)", -3.4011973816621555),+                                    ("integer (0..19)minute (grain)", -3.4011973816621555),+                                    ("integer (numeric)month (grain)", -3.4011973816621555),+                                    ("minute", -2.890371757896165),+                                    ("integer (numeric)hour (grain)", -3.1135153092103742),+                                    ("integer (0..19)day (grain)", -3.4011973816621555),+                                    ("integer (0..19)week (grain)", -3.1135153092103742)],+                               n = 33}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.8109302162163288),+                                    ("integer (numeric)time-of-day (latent)", -1.0986122886681098),+                                    ("integer (20..90)time-of-day (latent)", -1.5040773967762742)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("a <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.0794415416798357),+                                    ("hour (grain)", -2.4849066497880004),+                                    ("second", -2.0794415416798357),+                                    ("week (grain)", -2.0794415416798357),+                                    ("day", -2.4849066497880004),+                                    ("minute (grain)", -2.4849066497880004),+                                    ("second (grain)", -2.0794415416798357),+                                    ("hour", -2.4849066497880004), ("minute", -2.4849066497880004),+                                    ("day (grain)", -2.4849066497880004)],+                               n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -8.855339734144506e-2,+                               unseen = -4.948759890378168,+                               likelihoods =+                                 HashMap.fromList+                                   [("<named-month> <day-of-month> (ordinal)intersect",+                                     -4.248495242049359),+                                    ("at <time-of-day>named-day", -4.248495242049359),+                                    ("intersect by \",\"year", -3.8430301339411947),+                                    ("hh:mmintersect by \",\"", -3.8430301339411947),+                                    ("dayday", -1.8971199848858813),+                                    ("hh:mmnamed-day", -4.248495242049359),+                                    ("named-dayintersect by \",\"", -3.332204510175204),+                                    ("named-day<named-month> <day-of-month> (ordinal)",+                                     -3.1498829533812494),+                                    ("dayyear", -2.744417845273085),+                                    ("<named-month> <day-of-month> (non ordinal)intersect",+                                     -4.248495242049359),+                                    ("intersect by \",\"<day-of-month> (non ordinal) <named-month>",+                                     -3.8430301339411947),+                                    ("<named-month> <day-of-month> (non ordinal)named-day",+                                     -4.248495242049359),+                                    ("named-day<day-of-month> (non ordinal) <named-month>",+                                     -3.5553480614894135),+                                    ("named-day<named-month> <day-of-month> (non ordinal)",+                                     -3.1498829533812494),+                                    ("hh:mmintersect", -3.8430301339411947),+                                    ("intersect by \",\"intersect", -3.8430301339411947),+                                    ("named-dayintersect", -3.8430301339411947),+                                    ("at <time-of-day>intersect", -3.8430301339411947),+                                    ("dayminute", -2.5437471498109336),+                                    ("intersectyear", -3.8430301339411947),+                                    ("minuteday", -2.108429078553088),+                                    ("hh:mmabsorption of , after named day", -4.248495242049359),+                                    ("at <time-of-day>intersect by \",\"", -3.8430301339411947),+                                    ("at <time-of-day>absorption of , after named day",+                                     -4.248495242049359),+                                    ("intersectintersect", -3.8430301339411947),+                                    ("intersect by \",\"<day-of-month>(ordinal) <named-month>",+                                     -3.8430301339411947),+                                    ("named-day<day-of-month>(ordinal) <named-month>",+                                     -3.5553480614894135),+                                    ("<named-month> <day-of-month> (ordinal)named-day",+                                     -4.248495242049359),+                                    ("<named-month> <day-of-month> (ordinal)year",+                                     -3.8430301339411947),+                                    ("<named-month> <day-of-month> (non ordinal)year",+                                     -3.8430301339411947)],+                               n = 54},+                   koData =+                     ClassData{prior = -2.468099531471619, unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.9459101490553135),+                                    ("daymonth", -1.9459101490553135)],+                               n = 5}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -2.197890671877523e-2,+                               unseen = -3.8501476017100584,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 45},+                   koData =+                     ClassData{prior = -3.828641396489095, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("quarter after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.248495242049359,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 68},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> sharp",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.2992829841302609),+                                    ("time-of-day (latent)", -1.2992829841302609),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = -0.8649974374866046,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.4816045409242156),+                                    ("daymonth", -1.1451323043030026),+                                    ("named-daylast <cycle>", -2.3978952727983707),+                                    ("named-daynext <cycle>", -2.3978952727983707),+                                    ("named-dayintersect", -1.9924301646902063),+                                    ("dayweek", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.5465437063680699, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -1.3862943611198906),+                                    ("daymonth", -0.8472978603872037),+                                    ("named-dayintersect", -1.540445040947149)],+                               n = 11}}),+       ("<duration> ago",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716), ("day", -1.8562979903656263),+                                    ("year", -2.367123614131617),+                                    ("<integer> <unit-of-duration>", -0.9007865453381898),+                                    ("a <unit-of-duration>", -2.772588722239781),+                                    ("month", -2.367123614131617)],+                               n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <time>",+        Classifier{okData =+                     ClassData{prior = -2.8134107167600364, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.6094379124341003),+                                    ("named-day", -1.6094379124341003),+                                    ("hour", -2.0149030205422647),+                                    ("week-end", -2.0149030205422647)],+                               n = 3},+                   koData =+                     ClassData{prior = -6.187540371808753e-2,+                               unseen = -4.6443908991413725,+                               likelihoods =+                                 HashMap.fromList+                                   [("year (latent)", -1.7443572303334711),+                                    ("day", -1.9956716586143772),+                                    ("time-of-day (latent)", -1.7443572303334711),+                                    ("year", -1.7443572303334711),+                                    ("named-day", -3.536116699561526),+                                    ("intersect by \"of\", \"from\", \"'s\"", -3.536116699561526),+                                    ("<day-of-month> (ordinal)", -2.33214389523559),+                                    ("hour", -1.7443572303334711)],+                               n = 47}}),+       ("<day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -1.0360919316867756, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)", -1.1786549963416462),+                                    ("ordinal (digits)", -0.3677247801253174)],+                               n = 11},+                   koData =+                     ClassData{prior = -0.4382549309311553,+                               unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList [("ordinal (digits)", -4.652001563489282e-2)],+                               n = 20}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("until <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -0.8873031950009028),+                                    ("hour", -0.8873031950009028)],+                               n = 6},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.5040773967762742),+                                    ("hh:mm", -1.5040773967762742),+                                    ("minute", -1.0986122886681098)],+                               n = 2}}),+       ("<integer> and an half hours",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.6931471805599453),+                                    ("integer (0..19)", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("decimal number",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -1.791759469228055),+                                    ("day", -1.0986122886681098),+                                    ("named-day", -1.0986122886681098),+                                    ("month", -1.791759469228055)],+                               n = 4}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -2.9444389791664407,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.5040773967762742),+                                    ("month (grain)", -2.1972245773362196),+                                    ("year (grain)", -2.1972245773362196),+                                    ("week (grain)", -1.5040773967762742),+                                    ("year", -2.1972245773362196), ("month", -2.1972245773362196)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.8109302162163288, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6739764335716716),+                                    ("week (grain)", -1.6739764335716716),+                                    ("day", -1.6739764335716716),+                                    ("day (grain)", -1.6739764335716716)],+                               n = 4}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.912023005428146,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.793208009442517),+                                    ("integer (0..19)year (grain)", -3.1986731175506815),+                                    ("integer (numeric)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)hour (grain)", -3.1986731175506815),+                                    ("second", -2.793208009442517),+                                    ("integer (numeric)second (grain)", -3.1986731175506815),+                                    ("integer (numeric)year (grain)", -3.1986731175506815),+                                    ("day", -2.793208009442517), ("year", -2.793208009442517),+                                    ("integer (numeric)week (grain)", -3.1986731175506815),+                                    ("integer (0..19)month (grain)", -3.1986731175506815),+                                    ("integer (0..19)second (grain)", -3.1986731175506815),+                                    ("hour", -2.793208009442517), ("month", -2.793208009442517),+                                    ("integer (numeric)minute (grain)", -3.1986731175506815),+                                    ("integer (0..19)minute (grain)", -3.1986731175506815),+                                    ("integer (numeric)month (grain)", -3.1986731175506815),+                                    ("minute", -2.793208009442517),+                                    ("integer (numeric)hour (grain)", -3.1986731175506815),+                                    ("integer (0..19)day (grain)", -3.1986731175506815),+                                    ("integer (0..19)week (grain)", -3.1986731175506815)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("in <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.3694478524670215,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.258096538021482),+                                    ("<integer> more <unit-of-duration>", -3.258096538021482),+                                    ("number.number hours", -3.6635616461296463),+                                    ("second", -2.9704144655697013), ("day", -2.5649493574615367),+                                    ("half an hour", -3.6635616461296463),+                                    ("<integer> <unit-of-duration>", -1.3121863889661687),+                                    ("a <unit-of-duration>", -2.5649493574615367),+                                    ("<integer> and an half hours", -3.258096538021482),+                                    ("hour", -2.4107986776342782), ("minute", -1.466337068793427),+                                    ("about <duration>", -3.258096538021482)],+                               n = 33},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<datetime> - <datetime> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.579818495252942, unseen = -4.304065093204169,+                               likelihoods =+                                 HashMap.fromList+                                   [("<day-of-month>(ordinal) <named-month><day-of-month> (non ordinal) <named-month>",+                                     -2.498699971920336),+                                    ("<day-of-month> (non ordinal) <named-month><day-of-month>(ordinal) <named-month>",+                                     -2.498699971920336),+                                    ("minuteminute", -2.093234863812172),+                                    ("hh:mmhh:mm", -2.093234863812172),+                                    ("dayday", -1.2459370034249682),+                                    ("<day-of-month> (non ordinal) <named-month><day-of-month> (non ordinal) <named-month>",+                                     -2.498699971920336),+                                    ("<day-of-month>(ordinal) <named-month><day-of-month>(ordinal) <named-month>",+                                     -2.498699971920336)],+                               n = 28},+                   koData =+                     ClassData{prior = -0.8209805520698302, unseen = -4.127134385045092,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -1.7129785913749407),+                                    ("minuteminute", -2.164963715117998),+                                    ("hh:mmhh:mm", -3.417726683613366),+                                    ("dayyear", -3.012261575505202),+                                    ("year<hour-of-day> <integer> (as relative minutes)",+                                     -3.012261575505202),+                                    ("hh:mmintersect", -2.3191143949452564),+                                    ("named-month<day-of-month>(ordinal) <named-month>",+                                     -2.3191143949452564),+                                    ("dd/mmyear", -3.012261575505202),+                                    ("named-month<day-of-month> (non ordinal) <named-month>",+                                     -2.3191143949452564),+                                    ("<hour-of-day> <integer> (as relative minutes)year",+                                     -3.012261575505202),+                                    ("minuteyear", -3.012261575505202),+                                    ("yearminute", -3.012261575505202)],+                               n = 22}}),+       ("<time-of-day> - <time-of-day> (interval)",+        Classifier{okData =+                     ClassData{prior = -0.8109302162163288, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("minuteminute", -0.7985076962177716),+                                    ("hh:mmhh:mm", -0.7985076962177716)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.587786664902119, unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mmtime-of-day (latent)", -0.8754687373538999),+                                    ("minuteminute", -2.4849066497880004),+                                    ("hh:mmhh:mm", -2.4849066497880004),+                                    ("minutehour", -0.8754687373538999)],+                               n = 10}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.007333185232471,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.6026896854443837),+                                    ("integer (0..19)year (grain)", -3.295836866004329),+                                    ("integer (numeric)day (grain)", -2.890371757896165),+                                    ("second", -2.890371757896165),+                                    ("integer (numeric)second (grain)", -3.295836866004329),+                                    ("integer (numeric)year (grain)", -2.890371757896165),+                                    ("day", -2.6026896854443837), ("year", -2.6026896854443837),+                                    ("integer (numeric)week (grain)", -3.295836866004329),+                                    ("integer (0..19)month (grain)", -2.890371757896165),+                                    ("integer (0..19)second (grain)", -3.295836866004329),+                                    ("hour", -3.295836866004329), ("month", -2.6026896854443837),+                                    ("integer (numeric)minute (grain)", -3.295836866004329),+                                    ("integer (0..19)minute (grain)", -3.295836866004329),+                                    ("integer (numeric)month (grain)", -3.295836866004329),+                                    ("minute", -2.890371757896165),+                                    ("integer (numeric)hour (grain)", -3.295836866004329),+                                    ("integer (0..19)day (grain)", -3.295836866004329),+                                    ("integer (0..19)week (grain)", -2.890371757896165)],+                               n = 17},+                   koData =+                     ClassData{prior = -infinity, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month> (non ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.4418327522790392, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-monthinteger (numeric)", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 5}}),+       ("<day-of-month> (non ordinal) <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.1466034741918754, unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 19},+                   koData =+                     ClassData{prior = -1.9924301646902063,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 3}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = -1.9212175364649418,+                               unseen = -3.7612001156935624,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 41},+                   koData =+                     ClassData{prior = -0.158326051237739, unseen = -5.484796933490655,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 239}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.4816045409242156),+                                    ("week (grain)named-month", -1.9924301646902063),+                                    ("day (grain)intersect", -1.9924301646902063),+                                    ("weekmonth", -1.4816045409242156),+                                    ("day (grain)named-month", -1.9924301646902063),+                                    ("week (grain)intersect", -1.9924301646902063)],+                               n = 8},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month>(ordinal) <named-month> year",+        Classifier{okData =+                     ClassData{prior = -0.587786664902119, unseen = -2.639057329615259,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinals (first..31st)named-month", -1.466337068793427),+                                    ("ordinal (digits)named-month", -1.1786549963416462),+                                    ("month", -0.7731898882334817)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.8109302162163288,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("ordinal (digits)named-month", -0.7884573603642702),+                                    ("month", -0.7884573603642702)],+                               n = 4}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("after <time-of-day>",+        Classifier{okData =+                     ClassData{prior = -0.8109302162163288, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("at <time-of-day>", -1.7227665977411035),+                                    ("intersect", -2.2335922215070942),+                                    ("tomorrow", -2.2335922215070942), ("day", -2.2335922215070942),+                                    ("hour", -1.3862943611198906)],+                               n = 8},+                   koData =+                     ClassData{prior = -0.587786664902119, unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("lunch", -2.772588722239781),+                                    ("year (latent)", -2.0794415416798357),+                                    ("day", -2.367123614131617),+                                    ("time-of-day (latent)", -2.0794415416798357),+                                    ("year", -2.0794415416798357), ("hh:mm", -2.772588722239781),+                                    ("<day-of-month> (ordinal)", -2.367123614131617),+                                    ("hour", -1.8562979903656263), ("minute", -2.772588722239781)],+                               n = 10}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<month> dd-dd (interval)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-month", -0.6931471805599453),+                                    ("month", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("about <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("half an hour", -0.6931471805599453),+                                    ("minute", -0.6931471805599453)],+                               n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> (as relative minutes)",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.1354942159291497,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (numeric)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 10}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -1.2992829841302609,+                               unseen = -3.6375861597263857,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.917770732084279), ("intersect", -2.512305623976115),+                                    ("season", -2.001480000210124),+                                    ("next <cycle>", -2.917770732084279),+                                    ("named-month", -2.512305623976115),+                                    ("day", -2.001480000210124), ("hour", -2.2246235515243336),+                                    ("month", -2.001480000210124),+                                    ("week-end", -2.2246235515243336)],+                               n = 12},+                   koData =+                     ClassData{prior = -0.3184537311185346, unseen = -4.356708826689592,+                               likelihoods =+                                 HashMap.fromList+                                   [("intersect", -1.8588987720656835),+                                    ("named-month", -1.5105920777974677),+                                    ("day", -3.6506582412937383),+                                    ("time-of-day (latent)", -3.245193133185574),+                                    ("<day-of-month> (ordinal)", -3.6506582412937383),+                                    ("noon", -3.6506582412937383), ("hour", -2.7343675094195836),+                                    ("month", -1.0116009116784799),+                                    ("morning", -3.6506582412937383)],+                               n = 32}}),+       ("<named-month> <day-of-month> (ordinal)",+        Classifier{okData =+                     ClassData{prior = -0.4418327522790392, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("month", -0.6931471805599453),+                                    ("named-monthordinal (digits)", -0.6931471805599453)],+                               n = 9},+                   koData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -2.5649493574615367,+                               likelihoods =+                                 HashMap.fromList+                                   [("month", -0.6931471805599453),+                                    ("named-monthordinal (digits)", -0.6931471805599453)],+                               n = 5}}),+       ("within <duration>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.6931471805599453),+                                    ("<integer> <unit-of-duration>", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/TR.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.TR (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/UK.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.UK (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers = HashMap.fromList []
+ Duckling/Ranking/Classifiers/VI.hs view
@@ -0,0 +1,906 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.VI (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> am|pm", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.4986303506721723, unseen = -4.61512051684126,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 99},+                   koData =+                     ClassData{prior = -0.9348671174470905, unseen = -4.189654742026425,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 64}}),+       ("exactly <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day gi\7901", -1.6094379124341003),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889i",+                                     -1.6094379124341003),+                                    ("time-of-day (latent)", -1.6094379124341003),+                                    ("hour", -0.916290731874155)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ng\224y h\244m qua",+        Classifier{okData =+                     ClassData{prior = -0.5596157879354228, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.8472978603872037,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ng\224y dd/mm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("dd/mm",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5}}),+       ("<part-of-day> <time>",+        Classifier{okData =+                     ClassData{prior = -0.7884573603642702,+                               unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -1.128465251817791),+                                    ("noonh\244m nay", -2.833213344056216),+                                    ("lunchng\224y mai", -2.4277482359480516),+                                    ("morningnamed-day", -2.833213344056216),+                                    ("noonng\224y h\244m qua", -2.4277482359480516),+                                    ("noonng\224y mai", -2.4277482359480516),+                                    ("afternoonng\224y dd/mm", -2.833213344056216),+                                    ("afternoonng\224y mai", -2.833213344056216)],+                               n = 10},+                   koData =+                     ClassData{prior = -0.6061358035703156,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourday", -1.072636802264849),+                                    ("afternoon<day-of-month> (numeric with day symbol) <named-month>",+                                     -2.538973871058276),+                                    ("afternoongi\225ng sinh", -1.845826690498331),+                                    ("afternoonng\224y dd/mm/yyyy", -2.9444389791664407),+                                    ("noongi\225ng sinh", -2.9444389791664407),+                                    ("afternoonng\224y dd/mm", -2.9444389791664407),+                                    ("lunchgi\225ng sinh", -2.9444389791664407),+                                    ("afternoonintersect", -2.9444389791664407)],+                               n = 12}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (0..19)",+        Classifier{okData =+                     ClassData{prior = -1.452252328911688, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -0.2666286632539486,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36}}),+       ("<day-of-week> t\7899i",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = -1.4271163556401458,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -0.2744368457017603, unseen = -3.044522437723423,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 19}}),+       ("ng\224y h\244m kia",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("gi\225ng sinh",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -3.4657359027997265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 30}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = -1.791759469228055, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -0.1823215567939546,+                               unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.5070449009260846,+                               unseen = -5.0106352940962555,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> s\225ng|chi\7873u|t\7889ing\224y dd/mm",+                                     -3.6176519448255684),+                                    ("hourday", -3.6176519448255684),+                                    ("dayhour", -4.310799125385514),+                                    ("h\244m nay<time-of-day> s\225ng|chi\7873u|t\7889i",+                                     -4.310799125385514),+                                    ("monthyear", -3.3945083935113587),+                                    ("time-of-day gi\7901<part-of-day> <time>", -4.310799125385514),+                                    ("time-of-day gi\7901<time> n\224y", -4.310799125385514),+                                    ("month (numeric with month symbol)year (numeric with year symbol)",+                                     -3.6176519448255684),+                                    ("dayday", -2.6060510331470885),+                                    ("named-monthyear (numeric with year symbol)",+                                     -4.310799125385514),+                                    ("hourhour", -3.3945083935113587),+                                    ("named-day<day-of-month> (numeric with day symbol) <named-month>",+                                     -2.7013612129514133),+                                    ("intersectyear (numeric with year symbol)",+                                     -3.6176519448255684),+                                    ("dayyear", -2.4389969484839225),+                                    ("<ordinal> <cycle> of <time>year (numeric with year symbol)",+                                     -4.310799125385514),+                                    ("minutehour", -3.9053340172773496),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889iintersect",+                                     -3.9053340172773496),+                                    ("time-of-day gi\7901<part-of-day> (h\244m )?nay",+                                     -4.310799125385514),+                                    ("<day-of-month> (numeric with day symbol) <named-month>year (numeric with year symbol)",+                                     -3.2121868367174042),+                                    ("named-daynext <cycle>", -3.6176519448255684),+                                    ("named-dayintersect", -4.310799125385514),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889i<day-of-month> (numeric with day symbol) <named-month>",+                                     -3.3945083935113587),+                                    ("time-of-day gi\7901tonight", -4.310799125385514),+                                    ("minuteday", -2.8067217286092396),+                                    ("hh:mm<part-of-day> <time>", -4.310799125385514),+                                    ("<day-of-month> <named-month>year (numeric with year symbol)",+                                     -3.2121868367174042),+                                    ("at hh:mm<part-of-day> <time>", -4.310799125385514),+                                    ("dayweek", -3.0580361568901457),+                                    ("weekyear", -4.310799125385514),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889ing\224y dd/mm/yyyy",+                                     -4.310799125385514),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889ing\224y mai",+                                     -4.310799125385514),+                                    ("named-daythis <cycle>", -3.6176519448255684),+                                    ("seasonthis <cycle>", -4.310799125385514),+                                    ("minuteyear", -3.9053340172773496)],+                               n = 53},+                   koData =+                     ClassData{prior = -0.9219887529887928, unseen = -4.736198448394496,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> s\225ng|chi\7873u|t\7889ing\224y dd/mm",+                                     -4.034240638152395),+                                    ("hourday", -2.2424811689243405),+                                    ("dayhour", -4.034240638152395),+                                    ("monthyear", -2.7814776696570274),+                                    ("noonh\244m nay", -4.034240638152395),+                                    ("houryear", -4.034240638152395),+                                    ("month (numeric with month symbol)year (numeric with year symbol)",+                                     -2.7814776696570274),+                                    ("dayday", -2.5301632413761213),+                                    ("dayyear", -4.034240638152395),+                                    ("h\244m naytime-of-day gi\7901", -4.034240638152395),+                                    ("minutehour", -3.628775530044231),+                                    ("<part-of-day> <time>year (numeric with year symbol)",+                                     -4.034240638152395),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889igi\225ng sinh",+                                     -2.424802725718295),+                                    ("noonng\224y h\244m qua", -3.628775530044231),+                                    ("noongi\225ng sinh", -4.034240638152395),+                                    ("minuteday", -2.9356283494842854),+                                    ("hh:mm<part-of-day> <time>", -4.034240638152395),+                                    ("noonng\224y mai", -3.628775530044231),+                                    ("<day-of-month> <named-month>year (numeric with year symbol)",+                                     -4.034240638152395),+                                    ("named-daygi\225ng sinh", -2.5301632413761213),+                                    ("at hh:mm<part-of-day> <time>", -4.034240638152395)],+                               n = 35}}),+       ("time-of-day gi\7901",+        Classifier{okData =+                     ClassData{prior = -6.453852113757118e-2,+                               unseen = -4.174387269895637,+                               likelihoods =+                                 HashMap.fromList+                                   [("exactly <time-of-day>", -3.4657359027997265),+                                    ("about <time-of-day>", -3.0602707946915624),+                                    ("time-of-day (latent)", -0.8266785731844679),+                                    ("hour", -0.7248958788745256)],+                               n = 30},+                   koData =+                     ClassData{prior = -2.772588722239781, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.9808292530117262),+                                    ("hour", -0.9808292530117262)],+                               n = 2}}),+       ("<ordinal> <cycle> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("daymonth", -1.3862943611198906),+                                    ("day (grain)ordinalsnamed-month", -2.0794415416798357),+                                    ("day (grain)ordinalsmonth (numeric with month symbol)",+                                     -1.6739764335716716),+                                    ("week (grain)ordinalsintersect", -2.0794415416798357),+                                    ("weekmonth", -1.6739764335716716),+                                    ("week (grain)ordinalsmonth (numeric with month symbol)",+                                     -2.0794415416798357)],+                               n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("season",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = -0.5389965007326869, unseen = -2.772588722239781,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 14},+                   koData =+                     ClassData{prior = -0.8754687373538999,+                               unseen = -2.4849066497880004,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 10}}),+       ("quarter <number>",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter (grain)integer (numeric)", -1.2992829841302609),+                                    ("quarter (grain)integer (0..19)", -1.2992829841302609),+                                    ("quarter", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -1.0986122886681098,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarter (grain)integer (numeric)", -0.8472978603872037),+                                    ("quarter", -0.8472978603872037)],+                               n = 2}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.9459101490553135),+                                    ("month (grain)", -3.044522437723423),+                                    ("year (grain)", -2.128231705849268),+                                    ("week (grain)", -1.9459101490553135),+                                    ("quarter", -2.3513752571634776), ("year", -2.128231705849268),+                                    ("month", -3.044522437723423),+                                    ("quarter (grain)", -2.3513752571634776)],+                               n = 13},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("month (grain)", -2.639057329615259),+                                    ("hour (grain)", -2.639057329615259),+                                    ("year (grain)", -2.639057329615259),+                                    ("second", -2.3513752571634776), ("day", -2.639057329615259),+                                    ("minute (grain)", -2.639057329615259),+                                    ("year", -2.639057329615259),+                                    ("second (grain)", -2.3513752571634776),+                                    ("hour", -2.639057329615259), ("month", -2.639057329615259),+                                    ("minute", -2.639057329615259),+                                    ("day (grain)", -2.639057329615259)],+                               n = 13}}),+       ("ng\224y mai",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter <number> <year>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -1.0986122886681098),+                                    ("quarter (grain)integer (numeric)year (numeric with year symbol)",+                                     -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarterhour", -1.0986122886681098),+                                    ("quarter (grain)integer (numeric)time-of-day (latent)",+                                     -1.0986122886681098)],+                               n = 1}}),+       ("dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("after lunch",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm:ss",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> tr\432\7899c",+        Classifier{okData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.5040773967762742),+                                    ("named-day", -1.5040773967762742)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("gi\225ng sinh", -2.2512917986064953),+                                    ("<hour-of-day> <integer>", -2.2512917986064953),+                                    ("day", -2.2512917986064953),+                                    ("time-of-day (latent)", -1.3350010667323402),+                                    ("hour", -1.3350010667323402), ("minute", -2.2512917986064953)],+                               n = 6}}),+       ("ng\224y dd/mm/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time> n\224y",+        Classifier{okData =+                     ClassData{prior = -0.6061358035703156, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("season", -1.845826690498331),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889i",+                                     -2.2512917986064953),+                                    ("day", -1.845826690498331), ("noon", -1.845826690498331),+                                    ("hour", -1.3350010667323402),+                                    ("morning", -2.2512917986064953)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.4469189829363254),+                                    ("noon", -1.7346010553881064), ("hour", -1.041453874828161)],+                               n = 5}}),+       ("b\226y gi\7901",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer>",+        Classifier{okData =+                     ClassData{prior = -1.4469189829363254,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.7884573603642702),+                                    ("time-of-day gi\7901integer (numeric)", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.2682639865946794,+                               unseen = -3.4011973816621555,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)integer (0..19)", -0.7282385003712154),+                                    ("hour", -0.7282385003712154)],+                               n = 13}}),+       ("<time> t\7899i",+        Classifier{okData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.995732273553991,+                               likelihoods =+                                 HashMap.fromList+                                   [("month (numeric with month symbol)", -2.2512917986064953),+                                    ("day", -1.3350010667323402),+                                    ("named-day", -1.3350010667323402),+                                    ("month", -2.2512917986064953)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.9808292530117262, unseen = -2.772588722239781,+                               likelihoods =+                                 HashMap.fromList+                                   [("gi\225ng sinh", -2.0149030205422647),+                                    ("time-of-day gi\7901", -2.0149030205422647),+                                    ("<hour-of-day> <integer>", -2.0149030205422647),+                                    ("day", -2.0149030205422647), ("hour", -2.0149030205422647),+                                    ("minute", -2.0149030205422647)],+                               n = 3}}),+       ("<time-of-day> s\225ng|chi\7873u|t\7889i",+        Classifier{okData =+                     ClassData{prior = -5.129329438755058e-2,+                               unseen = -4.465908118654584,+                               likelihoods =+                                 HashMap.fromList+                                   [("exactly <time-of-day>", -3.7612001156935624),+                                    ("time-of-day gi\7901", -1.318853080324358),+                                    ("<hour-of-day> <integer>", -3.355735007585398),+                                    ("about <time-of-day>", -3.355735007585398),+                                    ("at hh:mm", -3.068052935133617),+                                    ("(hour-of-day) half", -3.355735007585398),+                                    ("hh:mm", -2.5084371471981943), ("hour", -1.1962507582320256),+                                    ("minute", -1.8152899666382492)],+                               n = 38},+                   koData =+                     ClassData{prior = -2.995732273553991, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -1.540445040947149),+                                    ("hour", -1.540445040947149)],+                               n = 2}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (numeric with month symbol)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.2231435513142097),+                                    ("integer (0..19)", -1.6094379124341003)],+                               n = 28},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (numeric with year symbol)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 11},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter <number> of <year>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarteryear", -1.0986122886681098),+                                    ("quarter (grain)integer (numeric)year (numeric with year symbol)",+                                     -1.0986122886681098)],+                               n = 1},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -1.9459101490553135,+                               likelihoods =+                                 HashMap.fromList+                                   [("quarterhour", -1.0986122886681098),+                                    ("quarter (grain)integer (numeric)time-of-day (latent)",+                                     -1.0986122886681098)],+                               n = 1}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = -0.916290731874155, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -0.5108256237659907,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.6109179126442243,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.6376087894007967),+                                    ("year (grain)", -2.1972245773362196),+                                    ("week (grain)", -1.6376087894007967),+                                    ("day", -2.890371757896165), ("quarter", -1.9740810260220096),+                                    ("year", -2.1972245773362196),+                                    ("quarter (grain)", -1.9740810260220096),+                                    ("day (grain)", -2.890371757896165)],+                               n = 14},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = -0.2876820724517809,+                               unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -1.3862943611198906,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("about <time-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day gi\7901", -1.6739764335716716),+                                    ("<time-of-day> s\225ng|chi\7873u|t\7889i",+                                     -1.6739764335716716),+                                    ("time-of-day (latent)", -1.6739764335716716),+                                    ("hour", -0.8266785731844679)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("time-of-day (latent)",+        Classifier{okData =+                     ClassData{prior = -0.6567795363890705,+                               unseen = -3.4339872044851463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.10536051565782628),+                                    ("integer (0..19)", -2.3025850929940455)],+                               n = 28},+                   koData =+                     ClassData{prior = -0.7308875085427924, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.4989911661189879),+                                    ("integer (0..19)", -0.9343092373768334)],+                               n = 26}}),+       ("at hh:mm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("(hour-of-day) half",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day gi\7901", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -2.995732273553991,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -5.225746673713201,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -3.42859635585027),+                                    ("integer (0..19)year (grain)", -4.527208644518379),+                                    ("integer (numeric)day (grain)", -3.0231312477421053),+                                    ("integer (0..19)hour (grain)", -3.834061463958434),+                                    ("second", -3.6109179126442243),+                                    ("integer (numeric)second (grain)", -3.6109179126442243),+                                    ("integer (numeric)year (grain)", -2.655406467616788),+                                    ("day", -2.822460552279954), ("year", -2.581298495463066),+                                    ("integer (numeric)week (grain)", -4.121743536410215),+                                    ("integer (0..19)month (grain)", -4.527208644518379),+                                    ("hour", -2.001480000210124), ("month", -2.042301994730379),+                                    ("integer (numeric)minute (grain)", -3.6109179126442243),+                                    ("integer (numeric)month (grain)", -2.084861609149175),+                                    ("minute", -3.6109179126442243),+                                    ("integer (numeric)hour (grain)", -2.129313371720009),+                                    ("integer (0..19)day (grain)", -4.121743536410215),+                                    ("integer (0..19)week (grain)", -3.834061463958434)],+                               n = 83}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("time-of-day (latent)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("h\244m nay",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm",+        Classifier{okData =+                     ClassData{prior = -8.701137698962981e-2,+                               unseen = -2.5649493574615367,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 11},+                   koData =+                     ClassData{prior = -2.4849066497880004,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4339872044851463,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 29},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \"of\", \"from\", \"'s\"",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3025850929940455,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynext <cycle>", -1.5040773967762742),+                                    ("dayweek", -0.8109302162163288),+                                    ("named-daythis <cycle>", -1.0986122886681098)],+                               n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<hour-of-day> <integer> ph\250t",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("time-of-day gi\7901integer (numeric)", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("noon",+        Classifier{okData =+                     ClassData{prior = -0.7621400520468967,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -0.6286086594223742,+                               unseen = -2.3025850929940455,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 8}}),+       ("ordinals",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("(hour-of-day) quarter",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("hour", -0.6931471805599453),+                                    ("time-of-day gi\7901integer (numeric)", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.7731898882334817, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.5649493574615367),+                                    ("month (grain)", -2.5649493574615367),+                                    ("year (grain)", -1.6486586255873816),+                                    ("week (grain)", -2.5649493574615367),+                                    ("year", -1.6486586255873816), ("month", -2.5649493574615367)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.6190392084062235, unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("month (grain)", -2.2335922215070942),+                                    ("hour (grain)", -2.639057329615259),+                                    ("year (grain)", -2.639057329615259),+                                    ("second", -2.639057329615259), ("day", -2.639057329615259),+                                    ("minute (grain)", -2.639057329615259),+                                    ("year", -2.639057329615259),+                                    ("second (grain)", -2.639057329615259),+                                    ("hour", -2.639057329615259), ("month", -2.2335922215070942),+                                    ("minute", -2.639057329615259),+                                    ("day (grain)", -2.639057329615259)],+                               n = 7}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.1431008436406733,+                               unseen = -3.7612001156935624,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)day (grain)", -2.639057329615259),+                                    ("second", -2.3513752571634776),+                                    ("integer (numeric)second (grain)", -2.3513752571634776),+                                    ("integer (numeric)year (grain)", -2.639057329615259),+                                    ("day", -2.639057329615259), ("year", -2.639057329615259),+                                    ("integer (0..19)month (grain)", -3.044522437723423),+                                    ("hour", -2.639057329615259), ("month", -2.639057329615259),+                                    ("integer (numeric)minute (grain)", -2.639057329615259),+                                    ("integer (numeric)month (grain)", -3.044522437723423),+                                    ("minute", -2.639057329615259),+                                    ("integer (numeric)hour (grain)", -2.639057329615259)],+                               n = 13},+                   koData =+                     ClassData{prior = -2.0149030205422647, unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.8971199848858813),+                                    ("integer (numeric)week (grain)", -2.3025850929940455),+                                    ("integer (0..19)week (grain)", -2.3025850929940455)],+                               n = 2}}),+       ("<day-of-month> <named-month>",+        Classifier{okData =+                     ClassData{prior = -0.10008345855698253,+                               unseen = -3.7376696182833684,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)month (numeric with month symbol)",+                                     -0.8232003088081431),+                                    ("integer (numeric)named-month", -2.6149597780361984),+                                    ("month", -0.7178397931503169)],+                               n = 19},+                   koData =+                     ClassData{prior = -2.3513752571634776,+                               unseen = -2.0794415416798357,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)month (numeric with month symbol)",+                                     -0.8472978603872037),+                                    ("month", -0.8472978603872037)],+                               n = 2}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.4657359027997265,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)day (grain)", -2.3353749158170367),+                                    ("integer (0..19)hour (grain)", -2.740840023925201),+                                    ("second", -2.740840023925201),+                                    ("integer (numeric)second (grain)", -2.740840023925201),+                                    ("integer (numeric)year (grain)", -2.740840023925201),+                                    ("day", -2.3353749158170367), ("year", -2.740840023925201),+                                    ("hour", -2.3353749158170367), ("month", -2.3353749158170367),+                                    ("integer (numeric)minute (grain)", -2.740840023925201),+                                    ("integer (numeric)month (grain)", -2.3353749158170367),+                                    ("minute", -2.740840023925201),+                                    ("integer (numeric)hour (grain)", -2.740840023925201)],+                               n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("quarter (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = -0.6190392084062235,+                               unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -0.7731898882334817,+                               unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6}}),+       ("<part-of-day> (h\244m )?nay",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("noon", -1.0116009116784799), ("hour", -0.7884573603642702),+                                    ("morning", -1.7047480922384253)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<day-of-month> (numeric with day symbol) <named-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.784189633918261,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)month (numeric with month symbol)",+                                     -0.8167611365271219),+                                    ("integer (numeric)named-month", -2.662587827025453),+                                    ("month", -0.7166776779701395)],+                               n = 20},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}})]
+ Duckling/Ranking/Classifiers/ZH.hs view
@@ -0,0 +1,753 @@+-- 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.++-----------------------------------------------------------------+-- Auto-generated by regenClassifiers+--+-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING+--  @generated+-----------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Duckling.Ranking.Classifiers.ZH (classifiers) where+import Prelude+import Duckling.Ranking.Types+import qualified Data.HashMap.Strict as HashMap+import Data.String++classifiers :: Classifiers+classifiers+  = HashMap.fromList+      [("<time> timezone",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods =+                                 HashMap.fromList+                                   [("<time-of-day> am|pm", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (numeric)",+        Classifier{okData =+                     ClassData{prior = -0.5292593254548287,+                               unseen = -3.8066624897703196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 43},+                   koData =+                     ClassData{prior = -0.8892620594862358,+                               unseen = -3.4657359027997265,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 30}}),+       ("the day before yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("today",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd",+        Classifier{okData =+                     ClassData{prior = -1.6094379124341003,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -0.2231435513142097, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4}}),+       ("absorption of , after named day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("tonight",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("month (grain)",+        Classifier{okData =+                     ClassData{prior = -1.0296194171811581,+                               unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -0.4418327522790392,+                               unseen = -3.6375861597263857,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 36}}),+       ("<time-of-day> o'clock",+        Classifier{okData =+                     ClassData{prior = -0.5108256237659907, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -0.916290731874155, unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.6931471805599453),+                                    ("hour", -0.6931471805599453)],+                               n = 4}}),+       ("national day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hour (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect",+        Classifier{okData =+                     ClassData{prior = -0.4473122180436648, unseen = -4.553876891600541,+                               likelihoods =+                                 HashMap.fromList+                                   [("children's day<part-of-day> <dim time>", -3.4446824936018943),+                                    ("year (numeric with year symbol)<named-month> <day-of-month>",+                                     -1.547562508716013),+                                    ("dayday", -1.978345424808467),+                                    ("hourhour", -2.9338568698359033),+                                    ("hourminute", -3.4446824936018943),+                                    ("absorption of , after named day<named-month> <day-of-month>",+                                     -1.978345424808467),+                                    ("dayminute", -3.4446824936018943),+                                    ("tonight<time-of-day> o'clock", -2.9338568698359033),+                                    ("<dim time> <part-of-day>relative minutes after|past <integer> (hour-of-day)",+                                     -3.4446824936018943),+                                    ("yearday", -1.547562508716013)],+                               n = 39},+                   koData =+                     ClassData{prior = -1.0198314108149953, unseen = -4.110873864173311,+                               likelihoods =+                                 HashMap.fromList+                                   [("children's day<part-of-day> <dim time>", -2.1484344131667874),+                                    ("dayhour", -2.4849066497880004),+                                    ("daymonth", -2.1484344131667874),+                                    ("<dim time> <part-of-day><time-of-day> o'clock",+                                     -2.995732273553991),+                                    ("year (numeric with year symbol)named-month",+                                     -2.1484344131667874),+                                    ("hourhour", -2.995732273553991),+                                    ("hourminute", -2.995732273553991),+                                    ("absorption of , after named daynamed-month",+                                     -2.1484344131667874),+                                    ("yearmonth", -2.1484344131667874),+                                    ("dayminute", -2.995732273553991),+                                    ("<dim time> <part-of-day>relative minutes after|past <integer> (hour-of-day)",+                                     -2.995732273553991)],+                               n = 22}}),+       ("year (grain)",+        Classifier{okData =+                     ClassData{prior = -1.2809338454620642,+                               unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -0.325422400434628, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 13}}),+       ("last tuesday, last july",+        Classifier{okData =+                     ClassData{prior = -1.3350010667323402, unseen = -3.332204510175204,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.8979415932059586),+                                    ("named-day", -0.8979415932059586)],+                               n = 10},+                   koData =+                     ClassData{prior = -0.3053816495511819,+                               unseen = -4.1588830833596715,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -1.0076405104623831),+                                    ("named-month", -3.4499875458315876),+                                    ("month (numeric with month symbol)", -2.3513752571634776),+                                    ("hour", -1.0076405104623831), ("month", -2.1972245773362196)],+                               n = 28}}),+       ("next <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.7884573603642702, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("month (grain)", -1.252762968495368),+                                    ("week (grain)", -1.540445040947149),+                                    ("month", -1.252762968495368)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.6061358035703156, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.8266785731844679),+                                    ("week (grain)", -0.8266785731844679)],+                               n = 6}}),+       ("last year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.295836866004329,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yyyy-mm-dd",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("mm/dd/yyyy",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("evening|night",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("yesterday",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("hh:mm (time-of-day)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<integer> (latent time-of-day)",+        Classifier{okData =+                     ClassData{prior = -1.540445040947149, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -1.0296194171811581),+                                    ("integer (0..10)", -0.4418327522790392)],+                               n = 12},+                   koData =+                     ClassData{prior = -0.2411620568168881,+                               unseen = -3.8501476017100584,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -2.2192034840549946),+                                    ("integer (0..10)", -0.11506932978478723)],+                               n = 44}}),+       ("nth <time> of <time>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("monthday", -0.7884573603642702),+                                    ("month (numeric with month symbol)ordinal (digits)named-day",+                                     -1.2992829841302609),+                                    ("named-monthordinal (digits)named-day", -1.2992829841302609)],+                               n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("named-month",+        Classifier{okData =+                     ClassData{prior = -4.255961441879589e-2,+                               unseen = -3.2188758248682006,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 23},+                   koData =+                     ClassData{prior = -3.1780538303479458,+                               unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1}}),+       ("month (numeric with month symbol)",+        Classifier{okData =+                     ClassData{prior = -0.15415067982725836,+                               unseen = -3.6635616461296463,+                               likelihoods =+                                 HashMap.fromList+                                   [("integer (numeric)", -0.9985288301111273),+                                    ("integer (0..10)", -0.4595323293784402)],+                               n = 36},+                   koData =+                     ClassData{prior = -1.9459101490553135,+                               unseen = -2.1972245773362196,+                               likelihoods =+                                 HashMap.fromList [("integer (0..10)", -0.13353139262452263)],+                               n = 6}}),+       ("week (grain)",+        Classifier{okData =+                     ClassData{prior = -0.8754687373538999,+                               unseen = -3.0910424533583156,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 20},+                   koData =+                     ClassData{prior = -0.5389965007326869,+                               unseen = -3.4011973816621555,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 28}}),+       ("valentine's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("year (numeric with year symbol)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 13},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("now",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("numbers prefix with -, negative or minus",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("integer (numeric)", 0.0)],+                               n = 4}}),+       ("tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this year",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 1},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("afternoon",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.9459101490553135,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 5},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.8754687373538999,+                               unseen = -3.2188758248682006,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.9808292530117262),+                                    ("year (grain)", -2.0794415416798357),+                                    ("week (grain)", -0.9808292530117262),+                                    ("year", -2.0794415416798357)],+                               n = 10},+                   koData =+                     ClassData{prior = -0.5389965007326869,+                               unseen = -3.4965075614664802,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.7576857016975165),+                                    ("week (grain)", -0.7576857016975165)],+                               n = 14}}),+       ("minute (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<dim time> <part-of-day>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -3.9889840465642745,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayhour", -0.7514160886839211),+                                    ("national dayevening|night", -2.871679624884012),+                                    ("<named-month> <day-of-month>morning", -1.405342556090585),+                                    ("named-daymorning", -1.7730673362159024),+                                    ("children's dayafternoon", -2.871679624884012)],+                               n = 24},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<part-of-day> <dim time>",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("tonight<integer> (latent time-of-day)", -1.916922612182061),+                                    ("hourhour", -1.329135947279942),+                                    ("afternoonrelative minutes after|past <integer> (hour-of-day)",+                                     -1.916922612182061),+                                    ("hourminute", -1.7346010553881064),+                                    ("afternoonhh:mm (time-of-day)", -2.833213344056216),+                                    ("tonight<time-of-day> o'clock", -1.916922612182061)],+                               n = 13},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -3.5553480614894135,+                               likelihoods =+                                 HashMap.fromList+                                   [("hourhour", -1.2237754316221157),+                                    ("afternoonrelative minutes after|past <integer> (hour-of-day)",+                                     -1.916922612182061),+                                    ("afternoon<time-of-day> o'clock", -1.916922612182061),+                                    ("hourminute", -1.916922612182061),+                                    ("afternoon<integer> (latent time-of-day)",+                                     -1.7346010553881064)],+                               n = 13}}),+       ("<integer> <unit-of-duration>",+        Classifier{okData =+                     ClassData{prior = -infinity, unseen = -2.833213344056216,+                               likelihoods = HashMap.fromList [], n = 0},+                   koData =+                     ClassData{prior = 0.0, unseen = -5.54907608489522,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.9802280870180256),+                                    ("integer (0..10)month (grain)", -1.9075912847531766),+                                    ("integer (0..10)hour (grain)", -2.9802280870180256),+                                    ("second", -3.242592351485517),+                                    ("integer (0..10)day (grain)", -3.4657359027997265),+                                    ("integer (0..10)year (grain)", -3.7534179752515073),+                                    ("integer (numeric)year (grain)", -2.906120114864304),+                                    ("integer (0..10)second (grain)", -3.242592351485517),+                                    ("day", -3.4657359027997265), ("year", -2.600738465313122),+                                    ("integer (0..10)minute (grain)", -2.9802280870180256),+                                    ("hour", -2.9802280870180256),+                                    ("integer (0..10)week (grain)", -2.9802280870180256),+                                    ("month", -1.6133518117552368),+                                    ("integer (numeric)month (grain)", -2.906120114864304),+                                    ("minute", -2.9802280870180256)],+                               n = 120}}),+       ("integer (11..19)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.639057329615259,+                               likelihoods = HashMap.fromList [("integer (0..10)", 0.0)], n = 12},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<time-of-day> am|pm",+        Classifier{okData =+                     ClassData{prior = -0.4700036292457356, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("hh:mm (time-of-day)", -1.252762968495368),+                                    ("<integer> (latent time-of-day)", -1.540445040947149),+                                    ("hour", -1.540445040947149), ("minute", -1.252762968495368)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.9808292530117262,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.916290731874155),+                                    ("hour", -0.916290731874155)],+                               n = 3}}),+       ("relative minutes after|past <integer> (hour-of-day)",+        Classifier{okData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)integer (11..19)",+                                     -0.7884573603642702),+                                    ("hour", -0.7884573603642702)],+                               n = 4},+                   koData =+                     ClassData{prior = -0.6931471805599453,+                               unseen = -2.4849066497880004,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)integer (0..10)",+                                     -0.7884573603642702),+                                    ("hour", -0.7884573603642702)],+                               n = 4}}),+       ("army's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("intersect by \",\"",+        Classifier{okData =+                     ClassData{prior = -0.40546510810816444,+                               unseen = -3.367295829986474,+                               likelihoods =+                                 HashMap.fromList+                                   [("dayday", -0.7672551527136672),+                                    ("named-day<named-month> <day-of-month>", -0.7672551527136672)],+                               n = 12},+                   koData =+                     ClassData{prior = -1.0986122886681098, unseen = -2.833213344056216,+                               likelihoods =+                                 HashMap.fromList+                                   [("named-daynamed-month", -0.8266785731844679),+                                    ("daymonth", -0.8266785731844679)],+                               n = 6}}),+       ("named-day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.406719247264253,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 80},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("second (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.3978952727983707,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 9},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("the day after tomorrow",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next <time>",+        Classifier{okData =+                     ClassData{prior = -2.2512917986064953,+                               unseen = -2.3978952727983707,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -1.2039728043259361),+                                    ("named-day", -1.2039728043259361)],+                               n = 2},+                   koData =+                     ClassData{prior = -0.11122563511022437,+                               unseen = -3.713572066704308,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -1.1239300966523995),+                                    ("month (numeric with month symbol)", -2.995732273553991),+                                    ("day", -2.0794415416798357),+                                    ("named-day", -2.0794415416798357),+                                    ("hour", -1.1239300966523995), ("month", -2.995732273553991)],+                               n = 17}}),+       ("last <cycle>",+        Classifier{okData =+                     ClassData{prior = -0.9555114450274363, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -1.540445040947149),+                                    ("month (grain)", -1.252762968495368),+                                    ("week (grain)", -1.540445040947149),+                                    ("month", -1.252762968495368)],+                               n = 5},+                   koData =+                     ClassData{prior = -0.48550781578170077,+                               unseen = -3.044522437723423,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -0.7985076962177716),+                                    ("week (grain)", -0.7985076962177716)],+                               n = 8}}),+       ("christmas",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("new year's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.6094379124341003,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 3},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("next n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.07753744390572,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.451005098112319),+                                    ("integer (0..10)month (grain)", -2.6741486494265287),+                                    ("integer (0..10)hour (grain)", -2.451005098112319),+                                    ("second", -2.6741486494265287),+                                    ("integer (0..10)day (grain)", -2.6741486494265287),+                                    ("integer (0..10)year (grain)", -3.367295829986474),+                                    ("integer (0..10)second (grain)", -2.6741486494265287),+                                    ("day", -2.6741486494265287), ("year", -3.367295829986474),+                                    ("integer (0..10)minute (grain)", -2.451005098112319),+                                    ("hour", -2.451005098112319),+                                    ("integer (0..10)week (grain)", -2.451005098112319),+                                    ("month", -2.6741486494265287), ("minute", -2.451005098112319)],+                               n = 22},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("children's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.791759469228055,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 4},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("<named-month> <day-of-month>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.770684624465665,+                               likelihoods =+                                 HashMap.fromList+                                   [("month (numeric with month symbol)integer (11..19)",+                                     -2.5649493574615367),+                                    ("named-monthinteger (11..19)", -2.5649493574615367),+                                    ("named-monthinteger (numeric)", -3.6635616461296463),+                                    ("month (numeric with month symbol)integer (numeric)",+                                     -2.1231166051824975),+                                    ("month", -0.7368222440626069),+                                    ("month (numeric with month symbol)integer (0..10)",+                                     -2.1231166051824975),+                                    ("named-monthinteger (0..10)", -2.277267285009756)],+                               n = 55},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.0794415416798357,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("integer (0..10)",+        Classifier{okData =+                     ClassData{prior = -0.5010216236693698,+                               unseen = -4.8283137373023015,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 123},+                   koData =+                     ClassData{prior = -0.9311793443679057, unseen = -4.406719247264253,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 80}}),+       ("last n <cycle>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -4.61512051684126,+                               likelihoods =+                                 HashMap.fromList+                                   [("week", -2.995732273553991),+                                    ("integer (0..10)month (grain)", -2.120263536200091),+                                    ("integer (0..10)hour (grain)", -2.4079456086518722),+                                    ("second", -2.659260036932778),+                                    ("integer (0..10)day (grain)", -2.995732273553991),+                                    ("integer (0..10)year (grain)", -3.506557897319982),+                                    ("integer (0..10)second (grain)", -2.659260036932778),+                                    ("day", -2.995732273553991), ("year", -3.506557897319982),+                                    ("integer (0..10)minute (grain)", -2.4079456086518722),+                                    ("hour", -2.4079456086518722),+                                    ("integer (0..10)week (grain)", -2.995732273553991),+                                    ("month", -2.120263536200091), ("minute", -2.4079456086518722)],+                               n = 43},+                   koData =+                     ClassData{prior = -infinity, unseen = -2.70805020110221,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this|next <day-of-week>",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.70805020110221,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.6931471805599453),+                                    ("named-day", -0.6931471805599453)],+                               n = 6},+                   koData =+                     ClassData{prior = -infinity, unseen = -1.0986122886681098,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("ordinal (digits)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("integer (0..10)", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("morning",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.890371757896165,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 16},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("week-end",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("day (grain)",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -2.1972245773362196,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 7},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("labor day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("women's day",+        Classifier{okData =+                     ClassData{prior = 0.0, unseen = -1.3862943611198906,+                               likelihoods = HashMap.fromList [("", 0.0)], n = 2},+                   koData =+                     ClassData{prior = -infinity, unseen = -0.6931471805599453,+                               likelihoods = HashMap.fromList [], n = 0}}),+       ("this <time>",+        Classifier{okData =+                     ClassData{prior = -0.35667494393873245,+                               unseen = -3.5263605246161616,+                               likelihoods =+                                 HashMap.fromList+                                   [("day", -0.9315582040049435),+                                    ("named-day", -0.9315582040049435),+                                    ("hour", -2.3978952727983707),+                                    ("week-end", -2.3978952727983707)],+                               n = 14},+                   koData =+                     ClassData{prior = -1.2039728043259361, unseen = -2.890371757896165,+                               likelihoods =+                                 HashMap.fromList+                                   [("<integer> (latent time-of-day)", -0.8873031950009028),+                                    ("hour", -0.8873031950009028)],+                               n = 6}})]
+ Duckling/Ranking/Extraction.hs view
@@ -0,0 +1,45 @@+-- 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 #-}+module Duckling.Ranking.Extraction+  ( extractFeatures+  ) where++import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import qualified Data.Text as Text+import Prelude+import TextShow (showt)++import Duckling.Dimensions.Types+import Duckling.Duration.Types (DurationData (DurationData))+import qualified Duckling.Duration.Types as TDuration+import Duckling.Ranking.Types+import Duckling.Time.Types (TimeData (TimeData))+import qualified Duckling.Time.Types as TTime+import Duckling.Types+++-- | Feature extraction+-- | Features:+-- | 1) Concatenation of the names of the rules involved in parsing `Node`+-- | 2) Concatenation of the grains for time-like dimensions+extractFeatures :: Node -> BagOfFeatures+extractFeatures node =+  HashMap.fromList $ (featRules, 1) : [ (featGrain, 1) | not (null grains) ]+  where+    featRules = Text.concat $ mapMaybe rule (children node)+    grains = mapMaybe (\x ->+      case token x of+        Token Duration (DurationData {TDuration.grain = g}) -> Just $ showt g+        Token Time (TimeData {TTime.timeGrain = g}) -> Just $ showt g+        Token TimeGrain g -> Just $ showt g+        _ -> Nothing+      ) $ children node+    featGrain = Text.concat grains
+ Duckling/Ranking/Rank.hs view
@@ -0,0 +1,68 @@+-- 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 RecordWildCards #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Ranking.Rank+  ( rank+  ) where++import Control.Arrow ((***))+import Control.Monad (join)+import qualified Data.HashMap.Strict as HashMap+import Data.HashSet (HashSet)+import qualified Data.HashSet as HashSet+import Data.Maybe+import qualified Data.Set as Set+import Prelude++import Duckling.Dimensions.Types+import Duckling.Ranking.Extraction+import Duckling.Ranking.Types+import Duckling.Types++classify :: Classifier -> BagOfFeatures -> (Class, Double)+classify Classifier {..} feats = if okScore >= koScore+  then (True, okScore)+  else (False, koScore)+  where+    (okScore, koScore) = join (***) (p feats) (okData, koData)+    p :: BagOfFeatures -> ClassData -> Double+    p feats ClassData{..} =+      prior + HashMap.foldrWithKey (\feat x res ->+        res + fromIntegral x * HashMap.lookupDefault unseen feat likelihoods+      ) 0.0 feats++score :: Classifiers -> Node -> Double+score classifiers node@Node {rule = Just rule, ..} =+  case HashMap.lookup rule classifiers of+    Just c -> let feats = extractFeatures node+      in snd (classify c feats) + sum (map (score classifiers) children)+    Nothing -> 0.0+score _ Node {rule = Nothing} = 0.0++-- | Return all superior candidates, as defined by the partial ordering+winners :: Ord a => [a] -> [a]+winners xs = filter (\x -> all ((/=) LT . compare x) xs) xs++-- | Return a curated list of tokens+rank+  :: Classifiers+  -> HashSet (Some Dimension)+  -> [ResolvedToken]+  -> [ResolvedToken]+rank classifiers targets tokens =+  Set.toList . Set.fromList+  . map (\(Candidate token _ _) -> token)+  . winners+  $ map makeCandidate tokens+  where+    makeCandidate :: ResolvedToken -> Candidate+    makeCandidate token@Resolved {node = n@Node {token = Token d _}} =+      Candidate token (score classifiers n) $ HashSet.member (This d) targets
+ Duckling/Ranking/Types.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Ranking.Types+  ( Feature+  , BagOfFeatures+  , Class+  , Datum+  , Dataset++  , Classifier(..)+  , Classifiers+  , ClassData(..)++  , infinity+  ) where+import Data.HashMap.Strict (HashMap)+import Data.Text (Text)+import Prelude++-- -----------------------------------------------------------------+-- Aliases++type Feature = Text+type BagOfFeatures = HashMap Feature Int+type Class = Bool+type Datum = (BagOfFeatures, Class)+type Dataset = HashMap Text [Datum]++-- -----------------------------------------------------------------+-- Classification++data Classifier = Classifier+  { okData :: ClassData+  , koData :: ClassData+  }+  deriving (Eq, Show)++type Classifiers = HashMap Text Classifier++data ClassData = ClassData+  { prior :: Double+  , unseen :: Double+  , likelihoods :: HashMap Feature Double+  , n :: Int+  }+  deriving (Eq, Show)++infinity :: Double+infinity = 1 / 0
+ Duckling/Regex/Types.hs view
@@ -0,0 +1,30 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Regex.Types+  ( GroupMatch(..)+  ) where++import Control.DeepSeq+import Data.Hashable+import Data.Text (Text)+import GHC.Generics+import Prelude+import Duckling.Resolve (Resolve(..))++data GroupMatch = GroupMatch [Text]+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve GroupMatch where+  type ResolvedValue GroupMatch = ()+  resolve _ _ = Nothing
+ Duckling/Resolve.hs view
@@ -0,0 +1,60 @@+-- 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 FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Resolve+  ( Context(..)+  , DucklingTime(..)+  , Resolve(..)+  , fromUTC+  , fromZonedTime+  , toUTC+  ) where++import Data.Aeson+import Data.String+import qualified Data.Time as Time+import qualified Data.Time.LocalTime.TimeZone.Series as Series+import Prelude++import Duckling.Lang++-- | Internal time reference.+-- We work as if we were in UTC time and use `ZoneSeriesTime` to house the info.+-- We convert to local time at resolution, using `fromUTC`.+newtype DucklingTime = DucklingTime Series.ZoneSeriesTime+  deriving (Eq, Show)++data Context = Context+  { referenceTime :: DucklingTime+  , lang :: Lang+  }+  deriving (Eq, Show)++class ToJSON (ResolvedValue a) => Resolve a where+  type ResolvedValue a+  resolve :: Context -> a -> Maybe (ResolvedValue a)++fromZonedTime :: Time.ZonedTime -> DucklingTime+fromZonedTime (Time.ZonedTime localTime timeZone) = DucklingTime $+  Series.ZoneSeriesTime (toUTC localTime) (Series.TimeZoneSeries timeZone [])++-- | Given a UTCTime and an TimeZone, build a ZonedTime (no conversion)+fromUTC :: Time.UTCTime -> Time.TimeZone -> Time.ZonedTime+fromUTC (Time.UTCTime day diffTime) timeZone = Time.ZonedTime localTime timeZone+  where+    localTime = Time.LocalTime day timeOfDay+    timeOfDay = Time.timeToTimeOfDay diffTime++-- | Given a LocalTime, build a UTCTime (no conversion)+toUTC :: Time.LocalTime -> Time.UTCTime+toUTC (Time.LocalTime day timeOfDay) = Time.UTCTime day diffTime+  where+    diffTime = Time.timeOfDayToTime timeOfDay
+ Duckling/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Rules+  ( allRules+  , rulesFor+  ) where++import Data.HashSet (HashSet)+import Prelude+import qualified Data.HashSet as HashSet++import Duckling.Dimensions+import Duckling.Dimensions.Types+import Duckling.Lang+import qualified Duckling.Rules.AR as ARRules+import qualified Duckling.Rules.Common as CommonRules+import qualified Duckling.Rules.DA as DARules+import qualified Duckling.Rules.DE as DERules+import qualified Duckling.Rules.EN as ENRules+import qualified Duckling.Rules.ES as ESRules+import qualified Duckling.Rules.ET as ETRules+import qualified Duckling.Rules.FR as FRRules+import qualified Duckling.Rules.GA as GARules+import qualified Duckling.Rules.HE as HERules+import qualified Duckling.Rules.HR as HRRules+import qualified Duckling.Rules.ID as IDRules+import qualified Duckling.Rules.IT as ITRules+import qualified Duckling.Rules.JA as JARules+import qualified Duckling.Rules.KO as KORules+import qualified Duckling.Rules.MY as MYRules+import qualified Duckling.Rules.NB as NBRules+import qualified Duckling.Rules.NL as NLRules+import qualified Duckling.Rules.PL as PLRules+import qualified Duckling.Rules.PT as PTRules+import qualified Duckling.Rules.RO as RORules+import qualified Duckling.Rules.RU as RURules+import qualified Duckling.Rules.SV as SVRules+import qualified Duckling.Rules.TR as TRRules+import qualified Duckling.Rules.UK as UKRules+import qualified Duckling.Rules.VI as VIRules+import qualified Duckling.Rules.ZH as ZHRules+import Duckling.Types++-- | Returns the minimal set of rules required for `targets`.+rulesFor :: Lang -> HashSet (Some Dimension) -> [Rule]+rulesFor lang targets+  | HashSet.null targets = allRules lang+  | otherwise = [ rules | dims <- HashSet.toList $ explicitDimensions targets+                        , rules <- rulesFor' lang dims ]++-- | Returns all the rules for `lang`.+-- We can't really use `allDimensions` as-is, since `TimeGrain` is not present.+allRules :: Lang -> [Rule]+allRules lang = concatMap (rulesFor' lang) . HashSet.toList .+  explicitDimensions . HashSet.fromList $ allDimensions lang++rulesFor' :: Lang -> Some Dimension -> [Rule]+rulesFor' lang dim = CommonRules.rules dim ++ langRules lang dim++langRules :: Lang -> Some Dimension -> [Rule]+langRules AR = ARRules.rules+langRules DA = DARules.rules+langRules DE = DERules.rules+langRules EN = ENRules.rules+langRules ES = ESRules.rules+langRules ET = ETRules.rules+langRules FR = FRRules.rules+langRules GA = GARules.rules+langRules HE = HERules.rules+langRules HR = HRRules.rules+langRules ID = IDRules.rules+langRules IT = ITRules.rules+langRules JA = JARules.rules+langRules KO = KORules.rules+langRules MY = MYRules.rules+langRules NB = NBRules.rules+langRules NL = NLRules.rules+langRules PL = PLRules.rules+langRules PT = PTRules.rules+langRules RO = RORules.rules+langRules RU = RURules.rules+langRules SV = SVRules.rules+langRules TR = TRRules.rules+langRules UK = UKRules.rules+langRules VI = VIRules.rules+langRules ZH = ZHRules.rules
+ Duckling/Rules/AR.hs view
@@ -0,0 +1,35 @@+-- 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 #-}++module Duckling.Rules.AR+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.AR.Rules as Numeral+import qualified Duckling.Ordinal.AR.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/Common.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.Common+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Distance.Rules as Distance+import qualified Duckling.Duration.Rules as Duration+import qualified Duckling.Email.Rules as Email+import qualified Duckling.AmountOfMoney.Rules as AmountOfMoney+import qualified Duckling.PhoneNumber.Rules as PhoneNumber+import qualified Duckling.Temperature.Rules as Temperature+import Duckling.Types+import qualified Duckling.Url.Rules as Url+import qualified Duckling.Volume.Rules as Volume++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = []+rules (This Email) = Email.rules+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = []+rules (This PhoneNumber) = PhoneNumber.rules+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = Url.rules+rules (This Volume) = Volume.rules
+ Duckling/Rules/DA.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.DA+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Duration.DA.Rules as Duration+import qualified Duckling.Numeral.DA.Rules as Numeral+import qualified Duckling.Ordinal.DA.Rules as Ordinal+import qualified Duckling.Time.DA.Rules as Time+import qualified Duckling.TimeGrain.DA.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/DE.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.DE+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Duration.DE.Rules as Duration+import qualified Duckling.Ordinal.DE.Rules as Ordinal+import qualified Duckling.Numeral.DE.Rules as Numeral+import qualified Duckling.Time.DE.Rules as Time+import qualified Duckling.TimeGrain.DE.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/EN.hs view
@@ -0,0 +1,44 @@+-- 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 #-}++module Duckling.Rules.EN+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.EN.Rules as AmountOfMoney+import qualified Duckling.Distance.EN.Rules as Distance+import qualified Duckling.Duration.EN.Rules as Duration+import qualified Duckling.Email.EN.Rules as Email+import qualified Duckling.Numeral.EN.Rules as Numeral+import qualified Duckling.Ordinal.EN.Rules as Ordinal+import qualified Duckling.Quantity.EN.Rules as Quantity+import qualified Duckling.Temperature.EN.Rules as Temperature+import qualified Duckling.Time.EN.Rules as Time+import qualified Duckling.TimeGrain.EN.Rules as TimeGrain+import Duckling.Types+import qualified Duckling.Volume.EN.Rules as Volume++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = Email.rules+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/ES.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.ES+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.ES.Rules as AmountOfMoney+import qualified Duckling.Distance.ES.Rules as Distance+import qualified Duckling.Numeral.ES.Rules as Numeral+import qualified Duckling.Ordinal.ES.Rules as Ordinal+import qualified Duckling.Temperature.ES.Rules as Temperature+import qualified Duckling.Time.ES.Rules as Time+import qualified Duckling.TimeGrain.ES.Rules as TimeGrain+import qualified Duckling.Volume.ES.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/ET.hs view
@@ -0,0 +1,35 @@+-- 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 #-}++module Duckling.Rules.ET+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.ET.Rules as Numeral+import qualified Duckling.Ordinal.ET.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/FR.hs view
@@ -0,0 +1,44 @@+-- 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 #-}++module Duckling.Rules.FR+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.FR.Rules as AmountOfMoney+import qualified Duckling.Distance.FR.Rules as Distance+import qualified Duckling.Duration.FR.Rules as Duration+import qualified Duckling.Email.FR.Rules as Email+import qualified Duckling.Numeral.FR.Rules as Numeral+import qualified Duckling.Ordinal.FR.Rules as Ordinal+import qualified Duckling.Quantity.FR.Rules as Quantity+import qualified Duckling.Temperature.FR.Rules as Temperature+import qualified Duckling.Time.FR.Rules as Time+import qualified Duckling.TimeGrain.FR.Rules as TimeGrain+import qualified Duckling.Volume.FR.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = Email.rules+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/GA.hs view
@@ -0,0 +1,42 @@+-- 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 #-}++module Duckling.Rules.GA+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.GA.Rules as AmountOfMoney+import qualified Duckling.Distance.GA.Rules as Distance+import qualified Duckling.Duration.GA.Rules as Duration+import qualified Duckling.Numeral.GA.Rules as Numeral+import qualified Duckling.Ordinal.GA.Rules as Ordinal+import qualified Duckling.Temperature.GA.Rules as Temperature+import qualified Duckling.Time.GA.Rules as Time+import qualified Duckling.TimeGrain.GA.Rules as TimeGrain+import qualified Duckling.Volume.GA.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/HE.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.HE+  ( rules+  ) where++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.Duration.HE.Rules as Duration+import qualified Duckling.Numeral.HE.Rules as Numeral+import qualified Duckling.Ordinal.HE.Rules as Ordinal+import qualified Duckling.TimeGrain.HE.Rules as TimeGrain+import qualified Duckling.Time.HE.Rules as Time++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/HR.hs view
@@ -0,0 +1,43 @@+-- 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 #-}++module Duckling.Rules.HR+  ( rules+  ) where++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.AmountOfMoney.HR.Rules as AmountOfMoney+import qualified Duckling.Distance.HR.Rules as Distance+import qualified Duckling.Duration.HR.Rules as Duration+import qualified Duckling.Numeral.HR.Rules as Numeral+import qualified Duckling.Ordinal.HR.Rules as Ordinal+import qualified Duckling.Quantity.HR.Rules as Quantity+import qualified Duckling.Temperature.HR.Rules as Temperature+import qualified Duckling.Time.HR.Rules as Time+import qualified Duckling.TimeGrain.HR.Rules as TimeGrain+import qualified Duckling.Volume.HR.Rules as Volume++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/ID.hs view
@@ -0,0 +1,36 @@+-- 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 #-}++module Duckling.Rules.ID+  ( rules+  ) where++import qualified Duckling.AmountOfMoney.ID.Rules as AmountOfMoney+import Duckling.Dimensions.Types+import qualified Duckling.Numeral.ID.Rules as Numeral+import qualified Duckling.Ordinal.ID.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/IT.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.IT+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Duration.IT.Rules as Duration+import qualified Duckling.Email.IT.Rules as Email+import qualified Duckling.Numeral.IT.Rules as Numeral+import qualified Duckling.Ordinal.IT.Rules as Ordinal+import qualified Duckling.Temperature.IT.Rules as Temperature+import qualified Duckling.Time.IT.Rules as Time+import qualified Duckling.TimeGrain.IT.Rules as TimeGrain+import qualified Duckling.Volume.IT.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = Email.rules+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/JA.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.JA+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.JA.Rules as Numeral+import qualified Duckling.Ordinal.JA.Rules as Ordinal+import qualified Duckling.Temperature.JA.Rules as Temperature+import qualified Duckling.TimeGrain.JA.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = []+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/KO.hs view
@@ -0,0 +1,43 @@+-- 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 #-}++module Duckling.Rules.KO+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.KO.Rules as AmountOfMoney+import qualified Duckling.Distance.KO.Rules as Distance+import qualified Duckling.Duration.KO.Rules as Duration+import qualified Duckling.Numeral.KO.Rules as Numeral+import qualified Duckling.Ordinal.KO.Rules as Ordinal+import qualified Duckling.Quantity.KO.Rules as Quantity+import qualified Duckling.Temperature.KO.Rules as Temperature+import qualified Duckling.Time.KO.Rules as Time+import qualified Duckling.TimeGrain.KO.Rules as TimeGrain+import Duckling.Types+import qualified Duckling.Volume.KO.Rules as Volume++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/MY.hs view
@@ -0,0 +1,34 @@+-- 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 #-}++module Duckling.Rules.MY+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.MY.Rules as Numeral+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = []+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/NB.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.NB+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.NB.Rules as AmountOfMoney+import qualified Duckling.Duration.NB.Rules as Duration+import qualified Duckling.Numeral.NB.Rules as Numeral+import qualified Duckling.Ordinal.NB.Rules as Ordinal+import qualified Duckling.Time.NB.Rules as Time+import qualified Duckling.TimeGrain.NB.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/NL.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.NL+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Distance.NL.Rules as Distance+import qualified Duckling.Numeral.NL.Rules as Numeral+import qualified Duckling.Ordinal.NL.Rules as Ordinal+import qualified Duckling.Volume.NL.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/PL.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.PL+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Duration.PL.Rules as Duration+import qualified Duckling.Numeral.PL.Rules as Numeral+import qualified Duckling.Ordinal.PL.Rules as Ordinal+import qualified Duckling.Time.PL.Rules as Time+import qualified Duckling.TimeGrain.PL.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/PT.hs view
@@ -0,0 +1,43 @@+-- 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 #-}++module Duckling.Rules.PT+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.PT.Rules as AmountOfMoney+import qualified Duckling.Distance.PT.Rules as Distance+import qualified Duckling.Numeral.PT.Rules as Numeral+import qualified Duckling.Ordinal.PT.Rules as Ordinal+import qualified Duckling.PhoneNumber.PT.Rules as PhoneNumber+import qualified Duckling.Quantity.PT.Rules as Quantity+import qualified Duckling.Temperature.PT.Rules as Temperature+import qualified Duckling.Time.PT.Rules as Time+import qualified Duckling.TimeGrain.PT.Rules as TimeGrain+import Duckling.Types+import qualified Duckling.Volume.PT.Rules as Volume++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = PhoneNumber.rules+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/RO.hs view
@@ -0,0 +1,43 @@+-- 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 #-}++module Duckling.Rules.RO+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.RO.Rules as AmountOfMoney+import qualified Duckling.Distance.RO.Rules as Distance+import qualified Duckling.Duration.RO.Rules as Duration+import qualified Duckling.Numeral.RO.Rules as Numeral+import qualified Duckling.Ordinal.RO.Rules as Ordinal+import qualified Duckling.Quantity.RO.Rules as Quantity+import qualified Duckling.Temperature.RO.Rules as Temperature+import qualified Duckling.Time.RO.Rules as Time+import qualified Duckling.TimeGrain.RO.Rules as TimeGrain+import qualified Duckling.Volume.RO.Rules as Volume+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = Distance.rules+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = Quantity.rules+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = Volume.rules
+ Duckling/Rules/RU.hs view
@@ -0,0 +1,35 @@+-- 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 #-}++module Duckling.Rules.RU+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.RU.Rules as Numeral+import qualified Duckling.Ordinal.RU.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/SV.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Rules.SV+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.AmountOfMoney.SV.Rules as AmountOfMoney+import qualified Duckling.Duration.SV.Rules as Duration+import qualified Duckling.Ordinal.SV.Rules as Ordinal+import qualified Duckling.Numeral.SV.Rules as Numeral+import qualified Duckling.Time.SV.Rules as Time+import qualified Duckling.TimeGrain.SV.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = Duration.rules+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/TR.hs view
@@ -0,0 +1,35 @@+-- 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 #-}++module Duckling.Rules.TR+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.TR.Rules as Numeral+import qualified Duckling.Ordinal.TR.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/UK.hs view
@@ -0,0 +1,35 @@+-- 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 #-}++module Duckling.Rules.UK+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.UK.Rules as Numeral+import qualified Duckling.Ordinal.UK.Rules as Ordinal+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = []+rules (This TimeGrain) = []+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/VI.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.VI+  ( rules+  ) where++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.AmountOfMoney.VI.Rules as AmountOfMoney+import qualified Duckling.Numeral.VI.Rules as Numeral+import qualified Duckling.Ordinal.VI.Rules as Ordinal+import qualified Duckling.TimeGrain.VI.Rules as TimeGrain+import qualified Duckling.Time.VI.Rules as Time++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = AmountOfMoney.rules+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = []+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Rules/ZH.hs view
@@ -0,0 +1,38 @@+-- 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 #-}++module Duckling.Rules.ZH+  ( rules+  ) where++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.ZH.Rules as Numeral+import qualified Duckling.Ordinal.ZH.Rules as Ordinal+import qualified Duckling.Temperature.ZH.Rules as Temperature+import qualified Duckling.Time.ZH.Rules as Time+import qualified Duckling.TimeGrain.ZH.Rules as TimeGrain+import Duckling.Types++rules :: Some Dimension -> [Rule]+rules (This Distance) = []+rules (This Duration) = []+rules (This Numeral) = Numeral.rules+rules (This Email) = []+rules (This AmountOfMoney) = []+rules (This Ordinal) = Ordinal.rules+rules (This PhoneNumber) = []+rules (This Quantity) = []+rules (This RegexMatch) = []+rules (This Temperature) = Temperature.rules+rules (This Time) = Time.rules+rules (This TimeGrain) = TimeGrain.rules+rules (This Url) = []+rules (This Volume) = []
+ Duckling/Temperature/EN/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.EN.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 degrees Celsius"+             , "thirty seven celsius"+             , "37 degrees Celsius"+             , "thirty seven celsius"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 degrees F"+             , "seventy Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 degrees"+             , "45 deg."+             ]+  , examples (TemperatureValue Degree (-2))+             [ "-2°"+             , "- 2 degrees"+             , "2 degrees below zero"+             , "2 below zero"+             ]+  ]
+ Duckling/Temperature/EN/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.EN.Rules+  ( rules ) where++import Data.Maybe+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Temperature.Types (TemperatureData(..))+import Duckling.Types++ruleTemperatureDegrees :: Rule+ruleTemperatureDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ dimension Temperature+    , regex "(deg(ree?)?s?\\.?)|°"+    ]+  , prod = \tokens -> case tokens of+    (Token Temperature td:_) -> Just . Token Temperature $+      withUnit TTemperature.Degree td+    _ -> Nothing+  }++ruleTemperatureCelsius :: Rule+ruleTemperatureCelsius = Rule+  { name = "<temp> Celsius"+  , pattern =+    [ dimension Temperature+    , regex "c(el[cs]?(ius)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+    (Token Temperature td:_) -> Just . Token Temperature $+      withUnit TTemperature.Celsius td+    _ -> Nothing+  }++ruleTemperatureFahrenheit :: Rule+ruleTemperatureFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?rh?eh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+    (Token Temperature td:_) -> Just . Token Temperature $+      withUnit TTemperature.Fahrenheit td+    _ -> Nothing+  }++ruleTemperatureBelowZero :: Rule+ruleTemperatureBelowZero = Rule+  { name = "<temp> below zero"+  , pattern =+    [ dimension Temperature+    , regex "below zero"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td@(TemperatureData {TTemperature.value = v}):_) ->+        case TTemperature.unit td of+          Nothing -> Just . Token Temperature . withUnit TTemperature.Degree $+            td {TTemperature.value = - v}+          _ -> Just . Token Temperature $ td {TTemperature.value = - v}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleTemperatureDegrees+  , ruleTemperatureCelsius+  , ruleTemperatureFahrenheit+  , ruleTemperatureBelowZero+  ]
+ Duckling/Temperature/ES/Corpus.hs view
@@ -0,0 +1,51 @@+-- 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.Temperature.ES.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ES}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 grados Celsius"+             , "37 grados C"+             , "treinta y siete celsius"+             , "37 centígrados"+             , "37 grados centígrados"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 grados F"+             , "setenta Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 grados"+             ]+  , examples (TemperatureValue Degree (-10))+             [ "-10°"+             , "- diez grados"+             , "10 bajo cero"+             ]+  ]
+ Duckling/Temperature/ES/Rules.hs view
@@ -0,0 +1,85 @@+-- 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 #-}++module Duckling.Temperature.ES.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempTemp :: Rule+ruleLatentTempTemp = Rule+  { name = "<latent temp> temp"+  , pattern =+    [ dimension Temperature+    , regex "(grados?)|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelsius :: Rule+ruleTempCelsius = Rule+  { name = "<temp> Celsius"+  , pattern =+    [ dimension Temperature+    , regex "(cent(i|\x00ed)grados?|c(el[cs]?(ius)?)?\\.?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?reh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleLatentTempTempBajoCero :: Rule+ruleLatentTempTempBajoCero = Rule+  { name = "<latent temp> temp bajo cero"+  , pattern =+    [ dimension Temperature+    , regex "bajo cero"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td@(TemperatureData {TTemperature.value = v}):_) ->+        case TTemperature.unit td of+          Nothing -> Just . Token Temperature . withUnit TTemperature.Degree $+            td {TTemperature.value = - v}+          _ -> Just . Token Temperature $ td {TTemperature.value = - v}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempTemp+  , ruleLatentTempTempBajoCero+  , ruleTempCelsius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/FR/Corpus.hs view
@@ -0,0 +1,53 @@+-- 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.Temperature.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 degres Celsius"+             , "37 degré C"+             , "trente sept celsius"+             , "37 degré C"+             , "trente sept celsius"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 degrès F"+             , "soixante-dix Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 degrés"+             , "45 deg."+             ]+  , examples (TemperatureValue Degree (-10))+             [ "-10°"+             , "- 10 degres"+             , "10 degres en dessous de zero"+             , "10 en dessous de zero"+             ]+  ]
+ Duckling/Temperature/FR/Rules.hs view
@@ -0,0 +1,85 @@+-- 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 #-}++module Duckling.Temperature.FR.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempDegrees :: Rule+ruleLatentTempDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ dimension Temperature+    , regex "(deg(r(\x00e9|e|\x00e8))?s?\\.?)|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelsius :: Rule+ruleTempCelsius = Rule+  { name = "<temp> Celsius"+  , pattern =+    [ dimension Temperature+    , regex "c(el[cs]?(ius)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?reh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleLatentTempEnDessousDeZero :: Rule+ruleLatentTempEnDessousDeZero = Rule+  { name = "<latent temp> en dessous de zero"+  , pattern =+    [ dimension Temperature+    , regex "en dessous de (0|z(\x00e9|e)ro)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td@(TemperatureData {TTemperature.value = v}):_) ->+        case TTemperature.unit td of+          Nothing -> Just . Token Temperature . withUnit TTemperature.Degree $+            td {TTemperature.value = - v}+          _ -> Just . Token Temperature $ td {TTemperature.value = - v}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempDegrees+  , ruleLatentTempEnDessousDeZero+  , ruleTempCelsius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/GA/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 céimeanna Celsius"+             , "37 céimeanna C"+             , "37 céimeanna ceinteagrád"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 céimeanna F"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 céimeanna"+             ]+  , examples (TemperatureValue Degree (-10))+             [ "-10°"+             , "- 10 céimeanna"+             , "10 céimeanna faoi bhun náid"+             , "10 faoi bhun náid"+             ]+  ]
+ Duckling/Temperature/GA/Rules.hs view
@@ -0,0 +1,85 @@+-- 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 #-}++module Duckling.Temperature.GA.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempCim :: Rule+ruleLatentTempCim = Rule+  { name = "<latent temp> céim"+  , pattern =+    [ dimension Temperature+    , regex "g?ch?(\x00e9|e)im(e(anna)?)?|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelsius :: Rule+ruleTempCelsius = Rule+  { name = "<temp> Celsius"+  , pattern =+    [ dimension Temperature+    , regex "ceinteagr(\x00e1|a)d|c(el[cs]?(ius)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?reh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleLatentTempFaoiBhunNid :: Rule+ruleLatentTempFaoiBhunNid = Rule+  { name = "<latent temp> faoi bhun náid"+  , pattern =+    [ dimension Temperature+    , regex "faoi bhun (0|n(a|\x00e1)id)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td@(TemperatureData {TTemperature.value = v}):_) ->+        case TTemperature.unit td of+          Nothing -> Just . Token Temperature . withUnit TTemperature.Degree $+            td {TTemperature.value = - v}+          _ -> Just . Token Temperature $ td {TTemperature.value = - v}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempCim+  , ruleLatentTempFaoiBhunNid+  , ruleTempCelsius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/HR/Corpus.hs view
@@ -0,0 +1,45 @@+-- 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.Temperature.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celzija"+             , "37 stupnjeva Celzija"+             , "trideset i sedam celzija"+             , "37 stupnjeva Celzija"+             , "trideset sedam celzija"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 stupnjeva F"+             , "sedamdeset Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 stupnjeva"+             , "45 deg."+             ]+  ]
+ Duckling/Temperature/HR/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.HR.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import Duckling.Types+import qualified Duckling.Temperature.Types as TTemperature++ruleLatentTempStupnjevi :: Rule+ruleLatentTempStupnjevi = Rule+  { name = "<latent temp> stupnjevi"+  , pattern =+    [ dimension Temperature+    , regex "deg\\.?|stupa?nj((ev)?a)?|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelzij :: Rule+ruleTempCelzij = Rule+  { name = "<temp> Celzij"+  , pattern =+    [ dimension Temperature+    , regex "c(elz?(ija?)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?rh?eh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempStupnjevi+  , ruleTempCelzij+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/Helpers.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.Helpers+  ( isLatent+  , withUnit+  ) where++import Data.Maybe+import Prelude++import Duckling.Dimensions.Types+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Temperature.Types (TemperatureData(..))+import Duckling.Types++-- -----------------------------------------------------------------+-- Patterns++isLatent :: Predicate+isLatent (Token Temperature (TemperatureData {TTemperature.unit = Nothing})) =+  True+isLatent _ = False++-- -----------------------------------------------------------------+-- Production++withUnit :: TTemperature.TemperatureUnit -> TemperatureData -> TemperatureData+withUnit u td = td {TTemperature.unit = Just u}
+ Duckling/Temperature/IT/Corpus.hs view
@@ -0,0 +1,52 @@+-- 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.Temperature.IT.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = IT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 ° centigradi"+             , "37 gradi Celsius"+             , "37 gradi Centigradi"+             , "trentasette celsius"+             , "trentasette gradi centigradi"+             ]+  , examples (TemperatureValue Celsius 1)+             [ "1 grado centigrado"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 gradi F"+             , "70 gradi Fahreneit"+             , "settanta Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 gradi"+             ]+  , examples (TemperatureValue Degree 1)+             [ "1 grado"+             ]+  ]
+ Duckling/Temperature/IT/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.IT.Rules+  ( rules ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import Duckling.Types+import qualified Duckling.Temperature.Types as TTemperature++ruleLatentTempDegrees :: Rule+ruleLatentTempDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ dimension Temperature+    , regex "(grad[io]?\\.?)|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelcius :: Rule+ruleTempCelcius = Rule+  { name = "<temp> Celcius"+  , pattern =+    [ dimension Temperature+    , regex "(c((el[cs]?(ius)?)|(entigrad[io]))?\\.?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?rh?eh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempDegrees+  , ruleTempCelcius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/JA/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.JA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = JA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "摂氏37°"+             , "摂氏37度"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "華氏70°"+             , "華氏70度"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45度"+             ]+  ]
+ Duckling/Temperature/JA/Rules.hs view
@@ -0,0 +1,97 @@+-- 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 #-}++module Duckling.Temperature.JA.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempDegrees :: Rule+ruleLatentTempDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelcius :: Rule+ruleTempCelcius = Rule+  { name = "<temp> Celcius"+  , pattern =+    [ dimension Temperature+    , regex "\x6442\x6c0f(\x00b0|\x5ea6)|(\x00b0)C"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleCelciusTemp :: Rule+ruleCelciusTemp = Rule+  { name = "Celcius <temp>"+  , pattern =+    [ regex "\x6442\x6c0f"+    , dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "\x83ef\x6c0f(\x00b0|\x5ea6)|(\x00b0)F"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleFahrenheitTemp :: Rule+ruleFahrenheitTemp = Rule+  { name = "Fahrenheit <temp>"+  , pattern =+    [ regex "\x83ef\x6c0f"+    , dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCelciusTemp+  , ruleFahrenheitTemp+  , ruleLatentTempDegrees+  , ruleTempCelcius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/KO/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "섭씨37°"+             , "섭씨37도"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "화씨70°"+             , "화씨70도"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45도"+             ]+  ]
+ Duckling/Temperature/KO/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.KO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempDegrees :: Rule+ruleLatentTempDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ Predicate isLatent+    , regex "\xb3c4|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTemp :: Rule+ruleTemp = Rule+  { name = "섭씨 <temp>"+  , pattern =+    [ regex "\xc12d\xc528"+    , dimension Temperature+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempC :: Rule+ruleTempC = Rule+  { name = "<temp> °C"+  , pattern =+    [ dimension Temperature+    , regex "c"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTemp2 :: Rule+ruleTemp2 = Rule+  { name = "화씨 <temp>"+  , pattern =+    [ regex "\xd654\xc528"+    , dimension Temperature+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleTempF :: Rule+ruleTempF = Rule+  { name = "<temp> °F"+  , pattern =+    [ dimension Temperature+    , regex "f"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempDegrees+  , ruleTemp+  , ruleTemp2+  , ruleTempC+  , ruleTempF+  ]
+ Duckling/Temperature/PT/Corpus.hs view
@@ -0,0 +1,51 @@+-- 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.Temperature.PT.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 graus Celsius"+             , "37 graus C"+             , "trinta e sete celsius"+             , "37 centígrados"+             , "37 graus centigrados"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 graus F"+             , "setenta Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 graus"+             ]+  , examples (TemperatureValue Degree (-10))+             [ "-10°"+             , "- dez graus"+             , "10 abaixo de zero"+             ]+  ]
+ Duckling/Temperature/PT/Rules.hs view
@@ -0,0 +1,85 @@+-- 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 #-}++module Duckling.Temperature.PT.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import Duckling.Temperature.Types (TemperatureData (..))+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempTemp :: Rule+ruleLatentTempTemp = Rule+  { name = "<latent temp> temp"+  , pattern =+    [ dimension Temperature+    , regex "(graus?)|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelsius :: Rule+ruleTempCelsius = Rule+  { name = "<temp> Celsius"+  , pattern =+    [ dimension Temperature+    , regex "(cent(i|\x00ed)grados?|c(el[cs]?(ius)?)?\\.?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?reh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleLatentTempTempAbaixoDeZero :: Rule+ruleLatentTempTempAbaixoDeZero = Rule+  { name = "<latent temp> temp abaixo de zero"+  , pattern =+    [ dimension Temperature+    , regex "((graus?)|\x00b0)?( abaixo (de)? zero)"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td@(TemperatureData {TTemperature.value = v}):_) ->+        case TTemperature.unit td of+          Nothing -> Just . Token Temperature . withUnit TTemperature.Degree $+            td {TTemperature.value = - v}+          _ -> Just . Token Temperature $ td {TTemperature.value = - v}+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempTemp+  , ruleLatentTempTempAbaixoDeZero+  , ruleTempCelsius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/RO/Corpus.hs view
@@ -0,0 +1,45 @@+-- 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.Temperature.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "37 ° celsius"+             , "37 grade Celsius"+             , "treizeci si sapte celsius"+             , "37 grade Celsius"+             , "treizeci si sapte celsius"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "70 ° Fahrenheit"+             , "70 grade F"+             , "saptezeci Fahrenheit"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45 grade"+             ]+  ]
+ Duckling/Temperature/RO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Temperature.RO.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempGrade :: Rule+ruleLatentTempGrade = Rule+  { name = "<latent temp> grade"+  , pattern =+    [ dimension Temperature+    , regex "(grade)|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelcius :: Rule+ruleTempCelcius = Rule+  { name = "<temp> Celcius"+  , pattern =+    [ dimension Temperature+    , regex "c(el[cs]?(ius)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "f(ah?rh?eh?n(h?eit)?)?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleLatentTempGrade+  , ruleTempCelcius+  , ruleTempFahrenheit+  ]
+ Duckling/Temperature/Rules.hs view
@@ -0,0 +1,43 @@+-- 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 #-}++module Duckling.Temperature.Rules+  ( rules+  ) where++import Data.String+import Prelude++import Duckling.Dimensions.Types+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Temperature.Types (TemperatureData (..))+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleNumeralAsTemp :: Rule+ruleNumeralAsTemp = Rule+  { name = "number as temp"+  , pattern =+    [ dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral nd:_) ->+        Just . Token Temperature $ TemperatureData+          { TTemperature.unit = Nothing+          , TTemperature.value = floor $ TNumeral.value nd+          }+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleNumeralAsTemp+  ]
+ Duckling/Temperature/Types.hs view
@@ -0,0 +1,56 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Temperature.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 TemperatureUnit =+  Degree | Celsius | Fahrenheit+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++instance ToJSON TemperatureUnit where+  toJSON = String . Text.toLower . Text.pack . show++data TemperatureData = TemperatureData+  { unit :: Maybe TemperatureUnit+  , value :: Int+  } deriving (Eq, Generic, Hashable, Show, Ord, NFData)++instance Resolve TemperatureData where+  type ResolvedValue TemperatureData = TemperatureValue+  resolve _ TemperatureData {unit = Nothing} = Nothing+  resolve _ TemperatureData {unit = Just unit, value} =+    Just TemperatureValue {vUnit = unit, vValue = value}++data TemperatureValue = TemperatureValue+  { vUnit :: TemperatureUnit+  , vValue :: Int+  } deriving (Eq, Show)++instance ToJSON TemperatureValue where+  toJSON (TemperatureValue unit value) = object+    [ "type" .= ("value" :: Text)+    , "value" .= value+    , "unit" .= unit+    ]
+ Duckling/Temperature/ZH/Corpus.hs view
@@ -0,0 +1,53 @@+-- 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.Temperature.ZH.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Temperature.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ZH}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (TemperatureValue Celsius 37)+             [ "37°C"+             , "摄氏37°"+             , "攝氏37°"+             , "摄氏37度"+             , "攝氏37度"+             , "37摄氏°"+             , "37攝氏°"+             , "37摄氏度"+             , "37攝氏度"+             ]+  , examples (TemperatureValue Fahrenheit 70)+             [ "70°F"+             , "华氏70°"+             , "華氏70°"+             , "华氏70度"+             , "華氏70度"+             , "70华氏°"+             , "70華氏°"+             , "70华氏度"+             , "70華氏度"+             ]+  , examples (TemperatureValue Degree 45)+             [ "45°"+             , "45度"+             ]+  ]
+ Duckling/Temperature/ZH/Rules.hs view
@@ -0,0 +1,97 @@+-- 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 #-}++module Duckling.Temperature.ZH.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Temperature.Helpers+import qualified Duckling.Temperature.Types as TTemperature+import Duckling.Types++ruleLatentTempDegrees :: Rule+ruleLatentTempDegrees = Rule+  { name = "<latent temp> degrees"+  , pattern =+    [ dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Degree td+      _ -> Nothing+  }++ruleTempCelcius :: Rule+ruleTempCelcius = Rule+  { name = "<temp> Celcius"+  , pattern =+    [ dimension Temperature+    , regex "(\x6444|\x651d)\x6c0f(\x00b0|\x5ea6)|(\x00b0)C"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleCelciusTemp :: Rule+ruleCelciusTemp = Rule+  { name = "Celcius <temp>"+  , pattern =+    [ regex "(\x6444|\x651d)\x6c0f"+    , dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Celsius td+      _ -> Nothing+  }++ruleTempFahrenheit :: Rule+ruleTempFahrenheit = Rule+  { name = "<temp> Fahrenheit"+  , pattern =+    [ dimension Temperature+    , regex "(\x534e|\x83ef)\x6c0f(\x00b0|\x5ea6)|(\x00b0)F"+    ]+  , prod = \tokens -> case tokens of+      (Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++ruleFahrenheitTemp :: Rule+ruleFahrenheitTemp = Rule+  { name = "Fahrenheit <temp>"+  , pattern =+    [ regex "(\x534e|\x83ef)\x6c0f"+    , dimension Temperature+    , regex "\x5ea6|\x00b0"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Temperature td:_) -> Just . Token Temperature $+        withUnit TTemperature.Fahrenheit td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleCelciusTemp+  , ruleFahrenheitTemp+  , ruleLatentTempDegrees+  , ruleTempCelcius+  , ruleTempFahrenheit+  ]
+ Duckling/Testing/Types.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE TupleSections #-}++module Duckling.Testing.Types+  ( Corpus+  , Datetime+  , Example+  , NegativeCorpus+  , TestPredicate+  , dt+  , examples+  , examplesCustom+  , parserCheck+  , refTime+  , testContext+  , zTime+  ) where++import Data.Aeson+import Data.Fixed (Pico)+import qualified Data.Time as Time+import Data.Text (Text)+import Prelude++import Duckling.Lang+import Duckling.Resolve+import Duckling.Types++type TestPredicate = Context -> ResolvedToken -> Bool+type Example = (Text, TestPredicate)+type Corpus = (Context, [Example])+type NegativeCorpus = (Context, [Text])++examplesCustom :: TestPredicate -> [Text] -> [Example]+examplesCustom check = map (, check)++simpleCheck :: ToJSON a => a -> TestPredicate+simpleCheck json _ (Resolved {jsonValue = v}) = toJSON json == v++parserCheck :: Eq a => a -> (Value -> Maybe a) -> TestPredicate+parserCheck expected parse _ (Resolved {jsonValue = v}) =+  maybe False (expected ==) $ parse v++examples :: ToJSON a => a -> [Text] -> [Example]+examples output = examplesCustom (simpleCheck output)++type Datetime = (Integer, Int, Int, Int, Int, Pico)++dt :: Datetime -> Time.UTCTime+dt (year, month, days, hours, minutes, seconds) = Time.UTCTime day diffTime+  where+    day = Time.fromGregorian year month days+    diffTime = Time.timeOfDayToTime $ Time.TimeOfDay hours minutes seconds++zTime :: Datetime -> Int -> Time.ZonedTime+zTime datetime offset = fromUTC (dt datetime) $ Time.hoursToTimeZone offset++refTime :: Datetime -> Int -> DucklingTime+refTime datetime offset = fromZonedTime $ zTime datetime offset++-- Tuesday Feb 12, 2013 at 4:30am is the "now" for the tests+testContext :: Context+testContext = Context+  {lang = EN, referenceTime = refTime (2013, 2, 12, 4, 30, 0) (-2)}
+ Duckling/Time/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.Corpus+  ( datetime+  , datetimeInterval+  , datetimeOpenInterval+  , examples+  ) where++import Data.Aeson+import qualified Data.HashMap.Strict as H+import Data.Text (Text)+import qualified Data.Time.LocalTime.TimeZone.Series as Series+import Prelude+import Data.String++import Duckling.Resolve+import Duckling.Testing.Types hiding (examples)+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Types hiding (Entity(..))++datetime :: Datetime -> Grain -> Context -> SingleTimeValue+datetime d g ctx =+  timeValue tzSeries TimeObject {start = dt d, end = Nothing, grain = g}+  where+    DucklingTime (Series.ZoneSeriesTime _ tzSeries) = referenceTime ctx++datetimeInterval :: (Datetime, Datetime) -> Grain -> Context -> SingleTimeValue+datetimeInterval (d1, d2) g ctx = timeValue tzSeries TimeObject+  {start = dt d1, end = Just $ dt d2, grain = g}+  where+    DucklingTime (Series.ZoneSeriesTime _ tzSeries) = referenceTime ctx++datetimeOpenInterval+  :: IntervalDirection -> Datetime -> Grain -> Context -> SingleTimeValue+datetimeOpenInterval dir d g ctx = openInterval tzSeries dir TimeObject+  {start = dt d, end = Nothing, grain = g}+  where+    DucklingTime (Series.ZoneSeriesTime _ tzSeries) = referenceTime ctx++check :: ToJSON a => (Context -> a) -> TestPredicate+check f context (Resolved {jsonValue}) = case jsonValue of+  Object o -> toJSON (f context) == (Object $ H.delete "values" o)+  _ -> False++examples :: ToJSON a => (Context -> a) -> [Text] -> [Example]+examples f = examplesCustom (check f)
+ Duckling/Time/DA/Corpus.hs view
@@ -0,0 +1,633 @@+-- 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.Time.DA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = DA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "nu"+             , "lige nu"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "i dag"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "i går"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "i morgen"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "mandag"+             , "man."+             , "på mandag"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Mandag den 18. februar"+             , "Man, 18 februar"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "tirsdag"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "torsdag"+             , "tors"+             , "tors."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "fredag"+             , "fre"+             , "fre."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "lørdag"+             , "lør"+             , "lør."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "søndag"+             , "søn"+             , "søn."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "Den første marts"+             , "1. marts"+             , "Den 1. marts"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "3 marts"+             , "den tredje marts"+             , "den 3. marts"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3 marts 2015"+             , "tredje marts 2015"+             , "3. marts 2015"+             , "3-3-2015"+             , "03-03-2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "På den 15."+             , "På den 15"+             , "Den 15."+             , "Den 15"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "den 15. februar"+             , "15. februar"+             , "februar 15"+             , "15-02"+             , "15/02"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "8 Aug"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "Oktober 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             , "31-10-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14april 2015"+             , "April 14, 2015"+             , "fjortende April 15"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "næste tirsdag"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "næste fredag igen"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "næste marts"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "næste marts igen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "Søndag, 10 feb"+             , "Søndag 10 Feb"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Ons, Feb13"+             , "Ons feb13"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Mandag, Feb 18"+             , "Man, februar 18"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "denne uge"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "sidste uge"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "næste uge"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "sidste måned"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "næste måned"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "dette kvartal"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "næste kvartal"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "tredje kvartal"+             , "3. kvartal"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4. kvartal 2018"+             , "fjerde kvartal 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "sidste år"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "i år"+             , "dette år"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "næste år"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "sidste søndag"+             , "søndag i sidste uge"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "sidste tirsdag"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "næste tirsdag"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "næste onsdag"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "onsdag i næste uge"+             , "onsdag næste uge"+             , "næste onsdag igen"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "næste fredag igen"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "mandag i denne uge"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "tirsdag i denne uge"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "onsdag i denne uge"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "i overmorgen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "i forgårs"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "sidste mandag i marts"+             , "sidste mandag i Marts"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "sidste søndag i marts 2014"+             , "sidste søndag i Marts 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "tredje dag i oktober"+             , "tredje dag i Oktober"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "første uge i oktober 2014"+             , "første uge i Oktober 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "sidste dag i oktober 2015"+             , "sidste dag i Oktober 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "sidste uge i september 2014"+             , "sidste uge i September 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "første tirsdag i oktober"+             , "første tirsdag i Oktober"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "tredje tirsdag i september 2014"+             , "tredje tirsdag i September 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "første onsdag i oktober 2014"+             , "første onsdag i Oktober 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "anden onsdag i oktober 2014"+             , "anden onsdag i Oktober 2014"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "klokken 3"+             , "kl. 3"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "klokken 15"+             , "kl. 15"+             , "15h"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "ca. kl. 15"+             , "cirka kl. 15"+             , "omkring klokken 15"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "imorgen klokken 17 sharp"+             , "imorgen kl. 17 præcis"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "kvarter over 15"+             , "kvart over 15"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "kl. 20 over 15"+             , "klokken 20 over 15"+             , "kl. 15:20"+             , "15:20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "15:30"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "kvarter i 12"+             , "kvart i 12"+             , "11:45"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "klokken 9 på lørdag"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "Fre, Jul 18, 2014 19:00"+             ]+  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)+             [ "Fre, Jul 18"+             , "Jul 18, Fre"+             ]+  , examples (datetime (2014, 9, 20, 19, 30, 0) Minute)+             [ "kl. 19:30, Lør, 20 sep"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "om 1 sekund"+             , "om ét sekund"+             , "om et sekund"+             , "ét sekund fra nu"+             , "et sekund fra nu"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "om 1 minut"+             , "om ét minut"+             , "om et minut"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "om 2 minutter"+             , "om to minutter"+             , "om 2 minutter mere"+             , "om to minutter mere"+             , "2 minutter fra nu"+             , "to minutter fra nu"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "om 60 minutter"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om en halv time"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "om 2,5 time"+             , "om 2 og en halv time"+             , "om to og en halv time"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "om én time"+             , "om 1 time"+             , "om 1t"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "om et par timer"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "om 24 timer"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "om en dag"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ "3 år fra i dag"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "om 7 dage"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "om en uge"+             , "om én uge"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om ca. en halv time"+             , "om cirka en halv time"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "7 dage siden"+             , "syv dage siden"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14 dage siden"+             , "fjorten dage siden"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "en uge siden"+             , "én uge siden"+             , "1 uge siden"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "3 uger siden"+             , "tre uger siden"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "3 måneder siden"+             , "tre måneder siden"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "to år siden"+             , "2 år siden"+             ]+  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetime (2013, 12, 0, 0, 0, 0) Month)+             [ "et år efter juleaften"+             , "ét år efter juleaften"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "denne sommer"+             , "den her sommer"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "denne vinter"+             , "den her vinter"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "1 juledag"+             , "1. juledag"+             , "første juledag"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "nytårsaftensdag"+             , "nytårsaften"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "nytårsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "i aften"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "sidste weekend"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "i morgen aften"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "i morgen middag"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "i går aftes"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "denne weekend"+             , "i weekenden"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "mandag morgen"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "sidste 2 sekunder"+             , "sidste to sekunder"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "næste 3 sekunder"+             , "næste tre sekunder"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "sidste 2 minutter"+             , "sidste to minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "næste 3 minutter"+             , "næste tre minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "sidste 1 time"+             , "seneste 1 time"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "næste 3 timer"+             , "næste tre timer"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "sidste 2 dage"+             , "sidste to dage"+             , "seneste 2 dage"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "næste 3 dage"+             , "næste tre dage"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "sidste 2 uger"+             , "sidste to uger"+             , "seneste to uger"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "næste 3 uger"+             , "næste tre uger"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "sidste 2 måneder"+             , "sidste to måneder"+             , "seneste to måneder"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "næste 3 måneder"+             , "næste tre måneder"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "sidste 2 år"+             , "sidste to år"+             , "seneste 2 år"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "næste 3 år"+             , "næste tre år"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13-15 juli"+             , "13-15 Juli"+             , "13 til 15 Juli"+             , "13 juli til 15 juli"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "8 Aug - 12 Aug"+             , "8 Aug - 12 aug"+             , "8 aug - 12 aug"+             , "8 august - 12 august"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             , "9:30 til 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "fra 9:30 - 11:00 på torsdag"+             , "fra 9:30 til 11:00 på torsdag"+             , "mellem 9:30 og 11:00 på torsdag"+             , "9:30 - 11:00 på torsdag"+             , "9:30 til 11:00 på torsdag"+             , "efter 9:30 men før 11:00 på torsdag"+             , "torsdag fra 9:30 til 11:00"+             , "torsdag mellem 9:30 og 11:00"+             , "fra 9:30 til 11:00 på torsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "torsdag fra 9 til 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-13:30"+             , "11:30-13:30"+             , "11:30-13:30"+             , "11:30-13:30"+             , "11:30-13:30"+             , "11:30-13:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "indenfor 2 uger"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "inden kl. 14"+             , "indtil kl. 14"+             , "inden klokken 14"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "@ 16 CET"+             , "kl. 16 CET"+             , "klokken 16 CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "torsdag kl. 8:00 GMT"+             , "torsdag klokken 8:00 GMT"+             , "torsdag 08:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "idag kl. 14"+             , "idag klokken 14"+             , "kl. 14"+             , "klokken 14"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)+             [ "25/4 kl. 16:00"+             , "25/4 klokken 16:00"+             , "25-04 klokken 16:00"+             , "25-4 kl. 16:00"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Minute)+             [ "15:00 i morgen"+             , "kl. 15:00 i morgen"+             , "klokken 15:00 i morgen"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "efter kl. 14"+             , "efter klokken 14"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "efter 5 dage"+             , "efter fem dage"+             ]+  , examples (datetime (2013, 2, 17, 4, 0, 0) Hour)+             [ "om 5 dage"+             , "om fem dage"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 14, 0, 0) Hour)+             [ "efter i morgen kl. 14"+             , "efter i morgen klokken 14"+             , "i morgen efter kl. 14"+             , "i morgen efter klokken 14"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "før kl. 11"+             , "før klokken 11"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 11, 0, 0) Hour)+             [ "i morgen før kl. 11"+             , "i morgen før klokken 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "om eftermiddagen"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "kl. 13:30"+             , "klokken 13:30"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "om 15 minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "efter frokost"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "denne morgen"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "næste mandag"+             ]+  ]
+ Duckling/Time/DA/Rules.hs view
@@ -0,0 +1,2007 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.DA.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Regex.Types+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "mandag|man\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "i overmorgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "december|dec\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "(et|\x00e9t)? ?kvart(er)? i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        t <- minutesBefore 15 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "halv time i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        t <- minutesBefore 30 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleConstitutionDay :: Rule+ruleConstitutionDay = Rule+  { name = "constitution day"+  , pattern =+    [ regex "grundlov'?s?'? dag"+    ]+  , prod = \_ -> tt $ monthDay 6 5+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "tirsdag|tirs?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "valentine'?s?( dag)?"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleTheOrdinalCycleOfTime :: Rule+ruleTheOrdinalCycleOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "af|i|fra"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "af|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "nyt\x00e5rsdag"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(sidste|seneste)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "l\x00f8rdag|l\x00f8r\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|til|indtil"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juli|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "afte(s|n(en)?)"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleTheDayofmonthNonOrdinal :: Rule+ruleTheDayofmonthNonOrdinal = Rule+  { name = "the <day-of-month> (non ordinal)"+  , pattern =+    [ regex "den"+    , Predicate $ isIntegerBetween 1 31+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt $ dayOfMonth n+      _ -> Nothing+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "om"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "lige nu|nu|(i )?dette \x00f8jeblik"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "sidste"+    , dimension TimeGrain+    , regex "af|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "fra"+    , dimension Time+    , regex "\\-|til|indtil"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "(et|\x00e9t)? ?kvart(er)? over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "halv time over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ regex "([012]?\\d|30|31)(ter|\\.)?"+    , regex "\\-|til"+    , regex "([012]?\\d|30|31)(ter|\\.)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       Token Time td:+       _) -> do+        v1 <- parseInt m1+        v2 <- parseInt m2+        from <- intersect td (dayOfMonth v1)+        to <- intersect td (dayOfMonth v2)+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "torsdag|tors?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "for\x00e5r"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 3 20, monthDay 6 21)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ regex "n(\x00e6)ste"+    , dimension Time+    , regex "igen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "midten af"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect td (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13)+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "middag|(kl(\\.|okken)?)? tolv"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "i dag|idag"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "(kommende|n(\x00e6)ste)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "i forg\x00e5rs"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "mellem"+    , Predicate isATimeOfDay+    , regex "og"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "n(\x00e6)ste|kommende"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "januar|jan\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTheCycleOfTime :: Rule+ruleTheCycleOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? af"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(cirka|ca\\.|-?ish)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleOnDate :: Rule+ruleOnDate = Rule+  { name = "on <date>"+  , pattern =+    [ regex "den|p\x00e5"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "marts|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "fra (i dag|nu)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) -> tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(til )?middag"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "sidste|seneste"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        m <- parseInt m2+        d <- parseInt m1+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "eftermiddag(en)?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "april|apr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ regex "sidste"+    , dimension Time+    , regex "igen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-2) False td+      _ -> Nothing+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "juleaften(sdag)?"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuart :: Rule+ruleHourofdayQuart = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(et|\x00e9t)? ?kvart(er)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "halv time"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "fredag|fre\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "efter"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour False v+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "af|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(efter|fra)"+    , Predicate isATimeOfDay+    , regex "((men )?f\x00f8r)|\\-|til|indtil"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "februar|feb\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "pr(\x00e6)cis( kl\\.| klokken)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleInduringThePartofday2 :: Rule+ruleInduringThePartofday2 = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    , regex "en|ten"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "vinter"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "sommer"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "mellem"+    , dimension Time+    , regex "og"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "nyt\x00e5rsaften(sdag)?"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "siden"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "i slutningen af"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $+        interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "efter arbejde"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 17, hour False 21)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "sidste|seneste"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain (- n)+      _ -> Nothing+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(sharp|pr(\x00e6)cis)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "indenfor"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt $+        interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "midnat|EOD"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(omkring|cirka|ca\\.)( kl\\.| klokken)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "(engang )?inden|indtil|f\x00f8r|op til"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "klokken|kl\\.|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juni|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "af|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "august|aug\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "(week(\\s|-)?end)(en)?"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "(omkring|cirka|ca.)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> Just . Token Duration $ dd+      _ -> Nothing+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "EOM"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleNthTimeAfterTime2 :: Rule+ruleNthTimeAfterTime2 = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "n(\x00e6)ste|kommende"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "i"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "n(\x00e6)ste"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain n+      _ -> Nothing+  }++ruleADuration :: Rule+ruleADuration = Rule+  { name = "a <duration>"+  , pattern =+    [ regex "(om )?en|et|\x00e9n|\x00e9t"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "morgen(en)?"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "i|denne"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "denne|dette|i|nuv(\x00e6)rende|indev(\x00e6)rende"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "(denne|dette|i|den her)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDurationHence :: Rule+ruleDurationHence = Rule+  { name = "<duration> hence"+  , pattern =+    [ dimension Duration+    , regex "hence"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "af|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "efter (frokost|middag)"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 13, hour False 17)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "p\x00e5 en"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        y <- getIntValue token+        tt . mkLatent $ year y+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "i g\x00e5r|ig\x00e5r"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "efter\x00e5r"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "(engang )?efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "((1\\.?)|f\x00f8rste)? ?juledag"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNight :: Rule+ruleNight = Rule+  { name = "night"+  , pattern =+    [ regex "nat(ten)?"+    ]+  , prod = \_ ->+      let from = hour False 0+          to = hour False 4+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "af|i|fra"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "maj"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s\x00f8ndag|s\x00f8n\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute False h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "i aften"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        y <- getIntValue token+        tt $ year y+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "oktober|okt\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "sidste"+    , Predicate isADayOfWeek+    , regex "af|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleFathersDay :: Rule+ruleFathersDay = Rule+  { name = "Father's Day"+  , pattern =+    [ regex "far'?s?'? dag"+    ]+  , prod = \_ -> tt $ monthDay 6 5+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])[\\/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|til|indtil"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "november|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter False TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "onsdag|ons\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTheDayofmonthOrdinal :: Rule+ruleTheDayofmonthOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "den"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++rulePartofdayOfTime :: Rule+rulePartofdayOfTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "(en |ten )?den"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "EOY"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "i morgen|imorgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "mor'?s? dag"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "h"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "september|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         n <- parseInt match+         td2 <- intersectDOM td token+         Token Time <$> intersect td2 (year n)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        s <- parseInt m3+        tt $ hourMinuteSecond False h m s+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleADuration+  , ruleAboutDuration+  , ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterLunch+  , ruleAfterTimeofday+  , ruleAfterWork+  , ruleAfternoon+  , ruleAtTimeofday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleConstitutionDay+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleDurationHence+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEvening+  , ruleExactlyTimeofday+  , ruleFathersDay+  , ruleFromDatetimeDatetimeInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmss+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleInduringThePartofday2+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntersectByOfFromS+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNight+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeAfterTime2+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , ruleOnANamedday+  , ruleOnDate+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePartofdayOfTime+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheCycleOfTime+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleTheDayofmonthNonOrdinal+  , ruleTheDayofmonthOrdinal+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleTheOrdinalCycleOfTime+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleTimeofdaySharp+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleTonight+  , ruleUntilTimeofday+  , ruleValentinesDay+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleHourofdayQuart+  , ruleHourofdayHalf+  , ruleTimezone+  ]
+ Duckling/Time/DE/Corpus.hs view
@@ -0,0 +1,618 @@+-- 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.Time.DE.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = DE}, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext {lang = DE}, examples)+  where+    examples =+      [ "ein Hotel"+      , "ein Angebot"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "jetzt"+             , "genau jetzt"+             , "gerade eben"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "heute"+             , "zu dieser zeit"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "gestern"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "morgen"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "montag"+             , "mo."+             , "diesen montag"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Montag, Feb 18"+             , "Montag, Februar 18"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "dienstag"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "donnerstag"+             , "do"+             , "do."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "freitag"+             , "fr."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "samstag"+             , "sa."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "sonntag"+             , "so."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1 märz"+             , "erster märz"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "märz 3"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "märz 3 2015"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "am 15ten"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15. februar"+             , "februar 15"+             , "15te februar"+             , "15.2."+             , "am 15.2."+             , "februar 15"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "Aug 8"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "Oktober 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31.10.1974"+             , "31.10.74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14 april 2015"+             , "April 14, 2015"+             , "14te April 15"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "nächsten dienstag"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "übernächsten freitag"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nächsten märz"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "übernächsten märz"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "Sonntag, Feb 10"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Mittwoch, Feb 13"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Montag, Feb 18"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "diese woche"+             , "kommende woche"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "letzte woche"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "nächste woche"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "letzten monat"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nächsten monat"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "dieses quartal"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "nächstes quartal"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "drittes quartal"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4tes quartal 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "letztes jahr"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "dieses jahr"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "nächstes jahr"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "letzten sonntag"+             , "sonntag der letzten woche"+             , "sonntag letzte woche"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "letzten dienstag"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "nächsten dienstag"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "nächsten mittwoch"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "mittwoch der nächsten woche"+             , "mittwoch nächste woche"+             , "mittwoch nach dem nächsten"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "freitag nach dem nächsten"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "montag dieser woche"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "dienstag dieser woche"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mittwoch dieser woche"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "übermorgen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "vorgestern"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "letzter montag im märz"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "letzter sonntag im märz 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "dritter tag im oktober"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "erste woche im oktober 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "letzter tag im oktober 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "letzte woche im september 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "erster dienstag im oktober"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "dritter dienstag im september 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "erster mittwoch im oktober 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "zweiter mittwoch im oktober 2014"+             ]+  , examples (datetime (2015, 1, 13, 0, 0, 0) Day)+             [ "dritter dienstag nach weihnachten 2014"+             ]+  , examples (datetime (2013, 2, 12, 4, 0, 0) Hour)+             [ "um 4 in der früh"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "um 3"+             , "3 uhr"+             , "um drei"+             ]+  , examples (datetime (2013, 2, 12, 3, 18, 0) Minute)+             [ "3:18 früh"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "um 3 am nachmittag"+             , "um 15"+             , "um 15 uhr"+             , "15 uhr"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "zirka 15 uhr"+             , "zirka 3 uhr am nachmittag"+             , "um ungefähr 15 uhr"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "pünktlich um 17 uhr morgen"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "um viertel nach 3"+             , "viertel nach drei Uhr"+             , "3 uhr 15 am nachmittag"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "um 20 nach 3"+             , "15:20 am nachmittag"+             , "15 uhr 20 nachmittags"+             , "zwanzig nach 3"+             , "15:20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "um halb 4"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "halb vier uhr nachmittags"+             , "halb vier am nachmittag"+             , "15:30"+             ]+  , examples (datetime (2013, 2, 13, 3, 30, 0) Minute)+             [ "3:30"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "viertel vor 12"+             , "11:45"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Second)+             [ "15 minuten vor 12"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 uhr am abend"+             , "heute abend um 20 Uhr"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Minute)+             [ "heute um 20:00"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "um 19:30 am fr, 20. Sept."+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "am samstag um 9 Uhr"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Hour)+             [ "Fr, 18. Juli 2014 7 uhr abends"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "in einer sekunde"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "in einer minute"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "in 2 minuten"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "in 60 minuten"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "in einer halben stunde"+             , "in 30 minuten"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "in 2.5 stunden"+             , "in zwei ein halb stunden"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "in einer stunde"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "in zwei stunden"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "in ein paar stunden"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "in 24 stunden"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "morgen"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ "in 3 Jahren"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "in 7 tagen"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "in 1 woche"+             , "in einer woche"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "in zirka einer halben stunde"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "vor 7 tagen"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "vor 14 tagen"+             ]+  , examples (datetime (2013, 1, 29, 0, 0, 0) Day)+             [ "vor zwei wochen"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "vor einer woche"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "vor drei wochen"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "vor drei monaten"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "vor zwei jahren"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "in 7 tagen"+             ]+  , examples (datetime (2013, 12, 0, 0, 0, 0) Month)+             [ "ein jahr nach weihnachten"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "diesen sommer"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "diesen winter"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "Weihnachten"+             , "Weihnachtstag"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "Silvester"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "Neujahrstag"+             , "Neujahr"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "Valentinstag"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "Muttertag"+             ]+  , examples (datetime (2013, 6, 16, 0, 0, 0) Day)+             [ "Vatertag"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "Tag der Deutschen Einheit"+             , "3. Oktober"+             ]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "Halloween"+             ]+  , examples (datetime (2013, 11, 1, 0, 0, 0) Day)+             [ "Allerheiligen"+             ]+  , examples (datetime (2013, 12, 6, 0, 0, 0) Day)+             [ "Nikolaus"+             , "Nikolaustag"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "heute abend"+             , "am abend"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "morgen abend"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "morgen mittag"+             , "morgen zu mittag"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "gestern abend"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "dieses wochenende"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 3, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "montag morgens"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 3, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "morgens am 15. februar"+             , "15. februar morgens"+             , "am morgen des 15. februar"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "letzte 2 sekunden"+             , "letzten zwei sekunden"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "nächste 3 sekunden"+             , "nächsten drei sekunden"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "letzte 2 minuten"+             , "letzten zwei minuten"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "nächste 3 minuten"+             , "nächsten drei minuten"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "nächste 3 stunden"+             , "nächsten drei stunden"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "letzte 2 tage"+             , "letzten zwei tage"+             , "vergangenen zwei tage"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "nächsten 3 tagen"+             , "nächsten drei tage"+             , "kommenden drei tagen"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 15, 0, 0, 0)) Day)+             [ "nächsten paar tagen"+             , "kommenden paar tagen"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "letzten 2 wochen"+             , "letzte zwei wochen"+             , "vergangenen 2 wochen"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "nächsten 3 wochen"+             , "nächste drei wochen"+             , "kommenden drei wochen"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "letzten 2 monaten"+             , "letzte zwei monate"+             , "vergangenen zwei monaten"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "nächsten 3 monaten"+             , "nächste drei monate"+             , "kommenden drei monaten"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "letzten 2 jahren"+             , "letzten zwei jahre"+             , "vergangenen zwei jahren"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "nächsten 3 jahren"+             , "kommenden drei jahren"+             , "nächste drei jahre"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13. - 15. Juli"+             , "13ter bis 15ter Juli"+             , "13 bis 15 Juli"+             , "13 - 15 Juli"+             , "Juli 13 - Juli 15"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "Aug 8 - Aug 12"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "am Donnerstag von 9:30 - 11:00"+             , "am Donnerstag zwischen 9:30 und 11:00"+             , "Donnerstag 9:30 - 11:00"+             , "am Donnerstag nach 9:30 aber vor 11:00"+             , "Donnerstag von 9:30 bis 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "Donnerstag Vormittag von 9 bis 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-13:30"+             ]+  , examples (datetime (2013, 9, 21, 1, 30, 0) Minute)+             [ "1:30 am Sa, 21. Sept"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "binnen 2 wochen"+             , "innerhalb von 2 wochen"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "bis 2 Uhr nachmittag"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 0, 0, 0) Hour)+             [ "bis zum ende des tages"+             ]+  , examples (datetimeOpenInterval Before (2013, 3, 1, 0, 0, 0) Month)+             [ "bis zum ende des monats"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "16 Uhr CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "donnerstag 8:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "heute um 14 Uhr"+             , "um 2"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "morgen um 15 Uhr"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "nach 14 Uhr"+             , "nach 14h"+             , "nach 2 Uhr"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "bis 11 uhr"+             , "bis 11h vormittags"+             , "bis 11 am vormittag"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "am nachmittag"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "um 13:30 am nachmittag"+             , "nachmittags um 1 uhr 30"+             , "13:30"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "in 15 minuten"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "nach dem mittagessen"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "nächsten montag"+             , "kommenden montag"+             ]+  , examples (datetime (2013, 12, 10, 0, 0, 0) Day)+             [ "10.12."+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 30, 0), (2013, 2, 12, 19, 1, 0)) Minute)+             [ "18:30h - 19:00h"+             ]+  ]
+ Duckling/Time/DE/Rules.hs view
@@ -0,0 +1,2024 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.DE.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "montags?|mo\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "dezember|dez\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "vor"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [regex "vie?rtel vor"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        t <- minutesBefore 15 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "halbe? vor"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        t <- minutesBefore 30 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "die?nstags?|di\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "valentin'?stag"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleTheOrdinalCycleOfTime :: Rule+ruleTheOrdinalCycleOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "der|die|das"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "im|in|von"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ regex "der|die|das"+    , dimension Ordinal+    , dimension Time+    , regex "im"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "neujahr(s?tag)?"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "letzten?|letztes"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "samstags?|sa\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|bis"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juli|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "abends?"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleTheDayofmonthNonOrdinal :: Rule+ruleTheDayofmonthNonOrdinal = Rule+  { name = "the <day-of-month> (non ordinal)"+  , pattern =+    [ regex "der"+    , Predicate $ isIntegerBetween 1 31+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "in"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "(genau)? ?jetzt|diesen moment|in diesem moment|gerade eben"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "letzte(r|n|s)?"+    , dimension TimeGrain+    , regex "um|im"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "vo[nm]"+    , dimension Time+    , regex "\\-|bis"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "nach"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "vie?rtel nach"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "halbe? nach"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ regex "([012]?\\d|30|31)(ter|\\.)?"+    , regex "\\-|bis"+    , regex "([012]?\\d|30|31)(ter|\\.)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       Token Time td:+       _) -> do+        v1 <- parseInt m1+        v2 <- parseInt m2+        from <- intersect (dayOfMonth v1) td+        to <- intersect (dayOfMonth v2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "donn?erstags?|do\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleAfterTomorrow :: Rule+ruleAfterTomorrow = Rule+  { name = "after tomorrow"+  , pattern =+    [ regex "(\x00fc)bermorgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ regex "der"+    , dimension TimeGrain+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ regex "der"+    , dimension TimeGrain+    , regex "vor"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "fr(\x00fc)hling|fr(\x00fc)hjahr"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ dimension Time+    , regex "nach dem n(\x00e4)chsten"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "die iden (des?)"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "mittags?|zw(\x00f6)lf (uhr)?"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "heute|(um diese zeit|zu dieser zeit|um diesen zeitpunkt|zu diesem zeitpunkt)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "diese(n|r)|kommenden|n(\x00e4)chsten"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "zwischen"+    , Predicate isATimeOfDay+    , regex "und"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "n(\x00e4)chste(r|n|s)?|kommende(r|n|s)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "januar|jan\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(um )?zirka|ungef(\x00e4)hr|etwa"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleOnDate :: Rule+ruleOnDate = Rule+  { name = "on <date>"+  , pattern =+    [ regex "am"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "m(\x00e4)rz|m(\x00e4)r\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "ab (heute|jetzt)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(am |zu )?mittags?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "letzte(r|n|s)?|vergangene(r|n|s)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "nach ?mittags?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "april|apr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ regex "vorletzten?|vor ?letztes?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-2) False td+      _ -> Nothing+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "heilig(er)? abend"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "(in|an|am|w(\x00e4)h?rend)( der| dem| des)?"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> <quarter> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "vie?rtel"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> <half> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "halbe?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "freitags?|fr\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by ','"+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "([012]?[1-9]|10|20|30|31)\\.(0?[1-9]|10|11|12)\\."+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        d <- parseInt m1+        m <- parseInt m2+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "nach"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour (n < 12) n+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(von|nach|ab|fr(\x00fc)hestens (um)?)"+    , Predicate isATimeOfDay+    , regex "((noch|aber|jedoch)? vor)|\\-|bis"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "februar|feb\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "genau|exakt|p(\x00fc)nktlich|punkt( um)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "winter"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "sommer"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleSchweizerBundesfeiertag :: Rule+ruleSchweizerBundesfeiertag = Rule+  { name = "Schweizer Bundesfeiertag"+  , pattern =+    [ regex "schweiz(er)? (bundes)?feiertag|bundes feiertag"+    ]+  , prod = \_ -> tt $ monthDay 8 1+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "zwischen"+    , dimension Time+    , regex "und"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "silvester"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ regex "vor"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "bis (zum)? ende (von)?|(noch)? vor"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $+        interval TTime.Closed (td, cycleNth TG.Second 0)+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "nach (der)? arbeit|(am)? feier ?abend"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 17, hour False 21)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleBeforeYesterday :: Rule+ruleBeforeYesterday = Rule+  { name = "before yesterday"+  , pattern =+    [ regex "vorgestern"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "letzten?|vergangenen?"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain (- n)+      _ -> Nothing+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "genau|exakt|p(\x00fc)nktlich|punkt( um)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleAllerheiligen :: Rule+ruleAllerheiligen = Rule+  { name = "Allerheiligen"+  , pattern =+    [ regex "allerheiligen?|aller heiligen?"+    ]+  , prod = \_ -> tt $ monthDay 11 1+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "binnen|innerhalb( von)?"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt $+        interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "mitternacht|EOD|tagesende|ende (des)? tag(es)?"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(um )?zirka|ungef(\x00e4)hr|etwa"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "vor|bis( zu[rm]?)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleSterreichischerNationalfeiertag :: Rule+ruleSterreichischerNationalfeiertag = Rule+  { name = "Österreichischer Nationalfeiertag"+  , pattern =+    [ regex "((\x00f6)sterreichischer?)? nationalfeiertag|national feiertag"+    ]+  , prod = \_ -> tt $ monthDay 10 26+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "um|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juni|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "im"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "august|aug\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "wochen ?ende?"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleTagDerDeutschenEinheit :: Rule+ruleTagDerDeutschenEinheit = Rule+  { name = "Tag der Deutschen Einheit"+  , pattern =+    [ regex "tag (der)? deutsc?hen? einheit"+    ]+  , prod = \_ -> tt $ monthDay 10 3+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "(das )?ende des monats?"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleNthTimeAfterTime2 :: Rule+ruleNthTimeAfterTime2 = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ regex "der|das"+    , dimension Ordinal+    , dimension Time+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "(n(\x00e4)chste|kommende)[ns]?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|10|11|12)-([012]?[1-9]|10|20|30|31)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by 'of', 'from', 's"+  , pattern =+    [ Predicate isNotLatent+    , regex "von|der|im"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "n(\x00e4)chsten?|kommenden?"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleADuration :: Rule+ruleADuration = Rule+  { name = "a <duration>"+  , pattern =+    [ regex "(in )?eine?(r|n)?"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "morgens|(in der )?fr(\x00fc)h|vor ?mittags?|am morgen"+    ]+  , prod = \_ ->+      let from = hour False 3+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "diesen?|dieses|heute"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "diese(r|n|s)?|kommende(r|n|s)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "diese(n|r|s)?|(im )?laufenden"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDurationHence :: Rule+ruleDurationHence = Rule+  { name = "<duration> hence"+  , pattern =+    [ dimension Duration+    , regex "hence"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "vom|von"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNikolaus :: Rule+ruleNikolaus = Rule+  { name = "Nikolaus"+  , pattern =+    [ regex "nikolaus(tag)?|nikolaus tag|nikolo"+    ]+  , prod = \_ -> tt $ monthDay 12 6+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "nach dem mittagessen|nachmittags?"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 13, hour False 17)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "an einem"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $+        liftM2 (||) (isIntegerBetween (- 10000) 0) (isIntegerBetween 25 999)+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        y <- getIntValue token+        tt . mkLatent $ year y+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "gestern"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "herbst"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "weih?nacht(en|stag)?"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNight :: Rule+ruleNight = Rule+  { name = "night"+  , pattern =+    [ regex "nachts?"+    ]+  , prod = \_ ->+      let from = hour False 0+          to = hour False 4+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "([ap])\\.?m\\.?(?:[\\s'\"-_{}\\[\\]()]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleHalfIntegerGermanStyleHourofday :: Rule+ruleHalfIntegerGermanStyleHourofday = Rule+  { name = "half <integer> (german style hour-of-day)"+  , pattern =+    [ regex "halb"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        t <- minutesBefore 30 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "im|in|von"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleAfterNextTime :: Rule+ruleAfterNextTime = Rule+  { name = "after next <time>"+  , pattern =+    [ regex "(\x00fc)ber ?n(\x00e4)chste[ns]?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mai"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sonntags?|so\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)(?:uhr|h)?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute False h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "heute? (am)? abends?"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        y <- getIntValue token+        tt $ year y+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "oktober|okt\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en?"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleHhmmMilitary :: Rule+ruleHhmmMilitary = Rule+  { name = "hhmm (military)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (h:m:_)):_) -> do+        hh <- parseInt h+        mm <- parseInt m+        tt . mkLatent $ hourMinute False hh mm+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "letzte(r|n|s)?"+    , Predicate isADayOfWeek+    , regex "um|im"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleFathersDay :: Rule+ruleFathersDay = Rule+  { name = "Father's Day"+  , pattern =+    [ regex "vatt?ertag|vatt?er (tag)?"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 2 7 6+  }++ruleHhmmMilitaryAmpm :: Rule+ruleHhmmMilitaryAmpm = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m\\.?(?:[\\s'\"-_{}\\[\\]()]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):Token RegexMatch (GroupMatch (ap:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|bis"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "november|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "nach"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) -> tt .+        cycleNthAfter False TG.Quarter (v - 1) $ cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mittwochs?|mi\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTheDayofmonthOrdinal :: Rule+ruleTheDayofmonthOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "der"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "vor"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++rulePartofdayOfTime :: Rule+rulePartofdayOfTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "des|von|vom|am"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "([012]?[1-9]|10|20|30|31)\\.(0?[1-9]|10|11|12)\\.(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "(das )?(EOY|jahr(es)? ?ende|ende (des )?jahr(es)?)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "morgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "mutt?ertag|mutt?er (tag)?"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day>  o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "uhr|h(?:[\\s'\"-_{}\\[\\]()]|$)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "september|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+        n <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year n)+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleADuration+  , ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterLunch+  , ruleAfterNextTime+  , ruleAfterTimeofday+  , ruleAfterTomorrow+  , ruleAfterWork+  , ruleAfternoon+  , ruleAllerheiligen+  , ruleAtTimeofday+  , ruleBeforeYesterday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleDatetimeDatetimeInterval+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleDurationHence+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEvening+  , ruleExactlyTimeofday+  , ruleFathersDay+  , ruleFromDatetimeDatetimeInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalfIntegerGermanStyleHourofday+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmMilitary+  , ruleHhmmMilitaryAmpm+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntersectByOfFromS+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNight+  , ruleNikolaus+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeAfterTime2+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , ruleOnANamedday+  , ruleOnDate+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePartofdayOfTime+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleSchweizerBundesfeiertag+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleSterreichischerNationalfeiertag+  , ruleTagDerDeutschenEinheit+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheDayofmonthNonOrdinal+  , ruleTheDayofmonthOrdinal+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleTheOrdinalCycleOfTime+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimeofdayAmpm+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleTimeofdaySharp+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleTonight+  , ruleUntilTimeofday+  , ruleValentinesDay+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleTimezone+  ]
+ Duckling/Time/EN/Corpus.hs view
@@ -0,0 +1,783 @@+-- 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.Time.EN.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext, examples)+  where+    examples =+      [ "laughing out loud"+      , "1 adult"+      , "we are separated"+      , "25"+      , "this is the one"+      , "in 61"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "now"+             , "right now"+             , "just now"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "today"+             , "at this time"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             ["yesterday"]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "tomorrow"+             , "tomorrows"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "monday"+             , "mon."+             , "this monday"+             , "Monday, Feb 18"+             , "Mon, February 18"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "tuesday"+             , "Tuesday the 19th"+             , "Tuesday 19th"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "Thu 15th"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "thursday"+             , "thu"+             , "thu."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "friday"+             , "fri"+             , "fri."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "saturday"+             , "sat"+             , "sat."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "sunday"+             , "sun"+             , "sun."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "the 1st of march"+             , "first of march"+             , "march first"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             ["march 3"]+  , examples (datetime (2013, 3, 15, 0, 0, 0) Day)+             ["the ides of march"]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "march 3 2015"+             , "march 3rd 2015"+             , "march third 2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "on the 15th"+             , "the 15th of february"+             , "15 of february"+             , "february the 15th"+             , "february 15"+             , "15th february"+             , "2/15"+             , "on 2/15"+             , "February 15"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             ["Aug 8"]+  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)+             [ "Fri, Jul 18"+             , "Jul 18, Fri"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Month)+             ["October 2014"]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "10/31/1974"+             , "10/31/74"+             , "10-31-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14april 2015"+             , "April 14, 2015"+             , "14th April 15"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "next tuesday"+             , "around next tuesday"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             ["friday after next"]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             ["next March"]+  , examples (datetime (2014, 3, 1, 0, 0, 0) Month)+             ["March after next"]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             ["Sunday, Feb 10"]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             ["Wed, Feb13"]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "this week"+             , "current week"+             , "coming week"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "last week"+             , "past week"+             , "previous week"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "next week"+             , "the following week"+             , "around next week"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Month)+             ["last month"]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             ["next month"]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "this quarter"+             , "this qtr"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "next quarter"+             , "next qtr"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "third quarter"+             , "3rd quarter"+             , "third qtr"+             , "3rd qtr"+             , "the 3rd qtr"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4th quarter 2018"+             , "4th qtr 2018"+             , "the 4th qtr of 2018"+             ]+  , examples (datetime (2012, 1, 1, 0, 0, 0) Year)+             [ "last year"+             , "last yr"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Year)+             [ "this year"+             , "current year"+             , "this yr"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Year)+             [ "next year"+             , "next yr"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "last sunday"+             , "sunday from last week"+             , "last week's sunday"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             ["last tuesday"]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             ["next tuesday"]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             ["next wednesday"]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "wednesday of next week"+             , "wednesday next week"+             , "wednesday after next"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             ["friday after next"]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             ["monday of this week"]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             ["tuesday of this week"]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             ["wednesday of this week"]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             ["the day after tomorrow"]+  , examples (datetime (2013, 2, 14, 17, 0, 0) Hour)+             [ "day after tomorrow 5pm"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             ["the day before yesterday"]+  , examples (datetime (2013, 2, 10, 8, 0, 0) Hour)+             [ "day before yesterday 8am"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             ["last Monday of March"]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             ["last Sunday of March 2014"]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             ["third day of october"]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             ["first week of october 2014"]+  , examples (datetime (2013, 10, 7, 0, 0, 0) Week)+             ["the week of october 6th"]+  , examples (datetime (2013, 10, 7, 0, 0, 0) Week)+             ["the week of october 7th"]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "last day of october 2015"+             , "last day in october 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             ["last week of september 2014"]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "first tuesday of october"+             , "first tuesday in october"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             ["third tuesday of september 2014"]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             ["first wednesday of october 2014"]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             ["second wednesday of october 2014"]+  , examples (datetime (2015, 1, 13, 0, 0, 0) Day)+             ["third tuesday after christmas 2014"]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "at 3am"+             , "3 in the AM"+             , "at 3 AM"+             , "3 oclock am"+             , "at three am"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18am"+             , "3:18a"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "at 3pm"+             , "@ 3pm"+             , "3PM"+             , "3pm"+             , "3 oclock pm"+             , "3 o'clock in the afternoon"+             , "3ish pm"+             , "3pm approximately"+             , "at about 3pm"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "at 15 past 3pm"+             , "a quarter past 3pm"+             , "3:15 in the afternoon"+             , "15:15"+             , "3:15pm"+             , "3:15PM"+             , "3:15p"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "at 20 past 3pm"+             , "3:20 in the afternoon"+             , "3:20 in afternoon"+             , "twenty after 3pm"+             , "3:20p"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "at half past three pm"+             , "half past 3 pm"+             , "15:30"+             , "3:30pm"+             , "3:30PM"+             , "330 p.m."+             , "3:30 p m"+             , "3:30"+             , "half three"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             ["15:23:24"]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "a quarter to noon"+             , "11:45am"+             , "15 to noon"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 tonight"+             , "eight tonight"+             , "8 this evening"+             , "at 8 in the evening"+             , "in the evening at eight"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             ["at 7:30 PM on Fri, Sep 20"]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             ["at 9am on Saturday"]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             ["on Saturday for 9am"]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             ["Fri, Jul 18, 2014 07:00 PM"]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "in a sec"+             , "one second from now"+             , "in 1\""+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "in a minute"+             , "in one minute"+             , "in 1'"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "in 2 minutes"+             , "in 2 more minutes"+             , "2 minutes from now"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             ["in 60 minutes"]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "in a quarter of an hour"+             , "in 1/4h"+             , "in 1/4 h"+             , "in 1/4 hour"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "in half an hour"+             , "in 1/2h"+             , "in 1/2 h"+             , "in 1/2 hour"+             ]+  , examples (datetime (2013, 2, 12, 5, 15, 0) Second)+             [ "in three-quarters of an hour"+             , "in 3/4h"+             , "in 3/4 h"+             , "in 3/4 hour"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "in 2.5 hours"+             , "in 2 and an half hours"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "in one hour"+             , "in 1h"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "in a couple hours"+             , "in a couple of hours"+             ]+  , examples (datetime (2013, 2, 12, 7, 30, 0) Minute)+             [ "in a few hours"+             , "in few hours"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             ["in 24 hours"]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "in a day"+             , "a day from now"+             ]+  , examples (datetime (2016, 2, 1, 0, 0, 0) Month)+             ["3 years from today"]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             ["in 7 days"]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "in 1 week"+             , "in a week"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             ["in about half an hour"]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             ["7 days ago"]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14 days Ago"+             , "a fortnight ago"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "a week ago"+             , "one week ago"+             , "1 week ago"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             ["three weeks ago"]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             ["three months ago"]+  , examples (datetime (2011, 2, 1, 0, 0, 0) Month)+             ["two years ago"]+  , examples (datetime (1954, 1, 1, 0, 0, 0) Year)+             ["1954"]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             ["7 days hence"]+  , examples (datetime (2013, 2, 26, 4, 0, 0) Hour)+             [ "14 days hence"+             , "a fortnight hence"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "a week hence"+             , "one week hence"+             , "1 week hence"+             ]+  , examples (datetime (2013, 3, 5, 0, 0, 0) Day)+             ["three weeks hence"]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             ["three months hence"]+  , examples (datetime (2015, 2, 1, 0, 0, 0) Month)+             ["two years hence"]+  , examples (datetime (2013, 12, 1, 0, 0, 0) Month)+             [ "one year After christmas"+             , "a year from Christmas"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "this Summer"+             , "current summer"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             ["this winter"]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "xmas"+             , "christmas"+             , "christmas day"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "new year's eve"+             , "new years eve"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "new year's day"+             , "new years day"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "valentine's day"+             , "valentine day"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "Mother's Day"+             , "next mothers day"+             ]+  , examples (datetime (2012, 5, 13, 0, 0, 0) Day)+             ["last mothers day"]+  , examples (datetime (2014, 5, 11, 0, 0, 0) Day)+             ["mothers day 2014"]+  , examples (datetime (2013, 6, 16, 0, 0, 0) Day)+             ["Father's Day"]+  , examples (datetime (2012, 6, 17, 0, 0, 0) Day)+             ["last fathers day"]+  , examples (datetime (1996, 6, 16, 0, 0, 0) Day)+             ["fathers day 1996"]+  , examples (datetime (2013, 5, 27, 0, 0, 0) Day)+             [ "memorial day"+             , "Next Memorial Day"+             ]+  , examples (datetime (2012, 5, 28, 0, 0, 0) Day)+             [ "last memorial day"+             , "memorial day of last year"+             ]+  , examples (datetimeInterval ((2013, 5, 24, 18, 0, 0), (2013, 5, 28, 0, 0, 0)) Hour)+             ["memorial day week-end"]+  , examples (datetime (2013, 7, 4, 0, 0, 0) Day)+             [ "independence day"+             , "4th of July"+             , "4 of july"+             ]+  , examples (datetime (2013, 9, 2, 0, 0, 0) Day)+             ["labor day"]+  , examples (datetime (2012, 9, 3, 0, 0, 0) Day)+             [ "labor day of last year"+             , "Labor Day 2012"+             ]+  , examples (datetimeInterval ((2013, 8, 30, 18, 0, 0), (2013, 9, 3, 0, 0, 0)) Hour)+             ["labor day weekend"]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "halloween"+             , "next halloween"+             , "Halloween 2013"+             ]+  , examples (datetime (2013, 11, 28, 0, 0, 0) Day)+             [ "thanksgiving day"+             , "thanksgiving"+             , "thanksgiving 2013"+             , "this thanksgiving"+             , "next thanksgiving day"+             ]+  , examples (datetime (2014, 11, 27, 0, 0, 0) Day)+             [ "thanksgiving of next year"+             , "thanksgiving 2014"+             ]+  {- FIXME (jodent) Doesn't work in Duckling either. t13908315+  , examples (datetime (2012, 11, 22, 0, 0, 0) Day)+             [ "last thanksgiving"+             , "thanksgiving day 2012"+             ]+  , examples (datetime (2016, 11, 24, 0, 0, 0) Day)+             ["thanksgiving 2016"]-}+  , examples (datetime (2014, 1, 20, 0, 0, 0) Day)+             [ "MLK day"+             , "next Martin Luther King day"+             , "this MLK day"+             ]+  , examples (datetime (2013, 1, 21, 0, 0, 0) Day)+             [ "last MLK day"+             , "MLK day 2013"+             ]+  , examples (datetime (2012, 1, 16, 0, 0, 0) Day)+             [ "MLK day of last year"+             , "MLK day 2012"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "this evening"+             , "today evening"+             , "tonight"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             ["this past weekend"]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             ["tomorrow evening"]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "tomorrow lunch"+             , "tomorrow at lunch"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             ["yesterday evening"]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             ["this week-end"]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             ["monday mOrnIng"]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 9, 0, 0)) Hour)+             [ "monday early in the morning"+             , "monday early morning"+             , "monday in the early hours of the morning"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "february the 15th in the morning"+             , "15 of february in the morning"+             , "morning of the 15th of february"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "last 2 seconds"+             , "last two seconds"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "next 3 seconds"+             , "next three seconds"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "last 2 minutes"+             , "last two minutes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "next 3 minutes"+             , "next three minutes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "last 1 hour"+             , "last one hour"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "next 3 hours"+             , "next three hours"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "last 2 days"+             , "last two days"+             , "past 2 days"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "next 3 days"+             , "next three days"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             ["next few days"]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "last 2 weeks"+             , "last two weeks"+             , "past 2 weeks"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "next 3 weeks"+             , "next three weeks"+             ]+  , examples (datetimeInterval ((2012, 12, 1, 0, 0, 0), (2013, 2, 1, 0, 0, 0)) Month)+             [ "last 2 months"+             , "last two months"+             ]+  , examples (datetimeInterval ((2013, 3, 1, 0, 0, 0), (2013, 6, 1, 0, 0, 0)) Month)+             [ "next 3 months"+             , "next three months"+             ]+  , examples (datetimeInterval ((2011, 1, 1, 0, 0, 0), (2013, 1, 1, 0, 0, 0)) Year)+             [ "last 2 years"+             , "last two years"+             ]+  , examples (datetimeInterval ((2014, 1, 1, 0, 0, 0), (2017, 1, 1, 0, 0, 0)) Year)+             [ "next 3 years"+             , "next three years"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "July 13-15"+             , "July 13 to 15"+             , "July 13 thru 15"+             , "July 13 through 15"+             , "July 13 - July 15"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             ["Aug 8 - Aug 12"]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             ["9:30 - 11:00"]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "from 9:30 - 11:00 on Thursday"+             , "between 9:30 and 11:00 on thursday"+             , "between 9:30 and 11:00 on thursday"+             , "between 9:30 and 11:00 on thursday"+             , "9:30 - 11:00 on Thursday"+             , "later than 9:30 but before 11:00 on Thursday"+             , "Thursday from 9:30 to 11:00"+             , "from 9:30 untill 11:00 on thursday"+             , "Thursday from 9:30 untill 11:00"+             , "9:30 till 11:00 on Thursday"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 1, 0, 0), (2013, 2, 13, 2, 31, 0)) Minute)+             [ "tomorrow in between 1-2:30 ish"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 15, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "3-4pm"+             , "from 3 to 4 in the PM"+             , "around 3-4pm"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 15, 30, 0), (2013, 2, 12, 19, 0, 0)) Minute)+             [ "3:30 to 6 PM"+             , "3:30-6 p.m."+             ]+  , examples (datetimeInterval ((2013, 2, 12, 8, 0, 0), (2013, 2, 12, 14, 0, 0)) Hour)+             [ "8am - 1pm"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "Thursday from 9a to 11a"+             , "this Thu 9-11am"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             ["11:30-1:30"]+  , examples (datetime (2013, 9, 21, 13, 30, 0) Minute)+             ["1:30 PM on Sat, Sep 21"]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             ["Within 2 weeks"]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 12, 14, 0, 0)) Second)+             ["by 2:00pm"]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 13, 0, 0, 0)) Second)+             ["by EOD"]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 3, 1, 0, 0, 0)) Second)+             ["by EOM"]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 4, 1, 0, 0, 0)) Second)+             ["by the end of next month"]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "4pm CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "Thursday 8:00 GMT"+             , "Thu at 8 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "today at 2pm"+             , "at 2pm"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)+             ["4/25 at 4:00pm"]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "3pm tomorrow"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Minute)+             [ "until 2:00pm"+             , "through 2:00pm"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             ["after 2 pm"]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             ["after 5 days"]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             ["before 11 am"]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             ["in the afternoon"]+  , examples (datetimeInterval ((2013, 2, 12, 8, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "8am until 6"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "at 1:30pm"+             , "1:30pm"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "in 15 minutes"+             , "in 15'"+             , "in 15"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             ["after lunch"]+  , examples (datetimeInterval ((2013, 2, 12, 15, 0, 0), (2013, 2, 12, 21, 0, 0)) Hour)+             [ "after school"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             , "approximately 1030"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             ["this morning"]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             ["next monday"]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "at 12pm"+             , "at noon"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "at 12am"+             , "at midnight"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             [ "March"+             , "in March"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "tomorrow afternoon at 5"+             , "at 5 tomorrow afternoon"+             , "at 5pm tomorrow"+             , "tomorrow at 5pm"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 13, 0, 0), (2013, 2, 13, 15, 0, 0)) Hour)+             [ "1pm-2pm tomorrow"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "on the first"+             , "the 1st"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "at 1030"+             , "around 1030"+             ]+  , examples (datetime (2013, 2, 12, 19, 30, 0) Minute)+             [ "at 730 in the evening"+             ]+  , examples (datetime (2013, 2, 13, 1, 50, 0) Minute)+             [ "tomorrow at 150ish"+             ]+  , examples (datetime (2013, 2, 12, 23, 0, 0) Hour)+             [ "tonight at 11"+             ]+  , examples (datetime (2013, 2, 12, 4, 23, 0) Minute)+    -- yes, the result is in the past, we may need to revisit+             [ "at 4:23"+             , "4:23am"+             ]+  ]
+ Duckling/Time/EN/Rules.hs view
@@ -0,0 +1,1597 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.EN.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Duration.Helpers (duration)+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleIntersectOf :: Rule+ruleIntersectOf = Rule+  { name = "intersect by \",\", \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "of|from|for|'s|,"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAbsorbOnTime :: Rule+ruleAbsorbOnTime = Rule+  { name = "on <date>"+  , pattern =+    [ regex "on"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleAbsorbOnADOW :: Rule+ruleAbsorbOnADOW = Rule+  { name = "on a <named-day>"+  , pattern =+    [ regex "on a"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleAbsorbInMonth :: Rule+ruleAbsorbInMonth = Rule+  { name = "in <named-month>"+  , pattern =+    [ regex "in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> Just token+      _ -> Nothing+  }++ruleAbsorbCommaTOD :: Rule+ruleAbsorbCommaTOD = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> Just token+      _ -> Nothing+  }++instants :: [(Text, String, TG.Grain, Int)]+instants =+  [ ("now", "((just|right)\\s*)?now|immediately", TG.Second, 0)+  , ("today", "todays?|(at this time)", TG.Day, 0)+  , ("tomorrow", "(tmrw?|tomm?or?rows?)", TG.Day, 1)+  , ("yesterday", "yesterdays?", TG.Day, - 1)+  , ("end of month", "(the )?(EOM|end of (the )?month)", TG.Month, 1)+  , ("end of year", "(the )?(EOY|end of (the )?year)", TG.Year, 1)+  ]++ruleInstants :: [Rule]+ruleInstants = map go instants+  where+    go (name, regexPattern, grain, n) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> tt $ cycleNth grain n+      }++ruleNextDOW :: Rule+ruleNextDOW = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "this|next"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "this|current|coming"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth 0 False td+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "next"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(this past|last|previous)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth (- 1) False td+      _ -> Nothing+  }++ruleTimeBeforeLastAfterNext :: Rule+ruleTimeBeforeLastAfterNext = Rule+  { name = "<time> before last|after next"+  , pattern =+    [ dimension Time+    , regex "(before last|after next)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (match:_)):_) ->+        tt $ predNth 1 (match == "after next") td+      _ -> Nothing+  }++ruleLastDOWOfTime :: Rule+ruleLastDOWOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "last"+    , Predicate isADayOfWeek+    , regex "of"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "last"+    , dimension TimeGrain+    , regex "of|in"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "of|in"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleTheNthTimeOfTime :: Rule+ruleTheNthTimeOfTime = Rule+  { name = "the nth <time> of <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension Time+    , regex "of|in"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+         predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleTheNthTimeAfterTime :: Rule+ruleTheNthTimeAfterTime = Rule+  { name = "the nth <time> after <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension Time+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern = [Predicate $ isIntegerBetween 1000 2100]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleYearPastLatent :: Rule+ruleYearPastLatent = Rule+ { name = "past year (latent)"+ , pattern =+   [ Predicate $+       liftM2 (||) (isIntegerBetween (- 10000) 0) (isIntegerBetween 25 999)+   ]+ , prod = \tokens -> case tokens of+     (token:_) -> do+       n <- getIntValue token+       tt . mkLatent $ year n+     _ -> Nothing+ }++ruleYearFutureLatent :: Rule+ruleYearFutureLatent = Rule+ { name = "future year (latent)"+ , pattern = [Predicate $ isIntegerBetween 2101 10000]+ , prod = \tokens -> case tokens of+     (token:_) -> do+       n <- getIntValue token+       tt . mkLatent $ year n+     _ -> Nothing+ }++ruleDOMLatent :: Rule+ruleDOMLatent = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern = [Predicate isDOMOrdinal]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ dayOfMonth n+      _ -> Nothing+  }++ruleTheDOMNumeral :: Rule+ruleTheDOMNumeral = Rule+  { name = "the <day-of-month> (number)"+  , pattern =+    [ regex "the"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ dayOfMonth n+      _ -> Nothing+  }++ruleTheDOMOrdinal :: Rule+ruleTheDOMOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "the"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       _) -> tt $ dayOfMonth v+      _ -> Nothing+  }++ruleNamedDOMOrdinal :: Rule+ruleNamedDOMOrdinal = Rule+  { name = "<named-month>|<named-day> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate $ liftM2 (||) isAMonth isADayOfWeek+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleMonthDOMNumeral :: Rule+ruleMonthDOMNumeral = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDOMOfMonth :: Rule+ruleDOMOfMonth = Rule+  { name = "<day-of-month> (ordinal or number) of <named-month>"+  , pattern =+    [ Predicate isDOMValue+    , regex "of|in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDOMMonth :: Rule+ruleDOMMonth = Rule+  { name = "<day-of-month> (ordinal or number) <named-month>"+  , pattern =+    [ Predicate isDOMValue+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDOMOrdinalMonthYear :: Rule+ruleDOMOrdinalMonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:Token RegexMatch (GroupMatch (match:_)):_) -> do+        intVal <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year intVal)+      _ -> Nothing+  }++ruleIdesOfMonth :: Rule+ruleIdesOfMonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "the ides? of"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect td (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13)+      _ -> Nothing+  }++ruleTODLatent :: Rule+ruleTODLatent = Rule+  { name = "time-of-day (latent)"+  , pattern = [Predicate $ isIntegerBetween 0 23]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour True n+      _ -> Nothing+  }++ruleAtTOD :: Rule+ruleAtTOD = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "at|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleTODOClock :: Rule+ruleTODOClock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "o.?clock"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleHHMM :: Rule+ruleHHMM = Rule+  { name = "hh:mm"+  , pattern = [regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleHHMMLatent :: Rule+ruleHHMMLatent = Rule+  { name = "hhmm (latent)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . mkLatent $ hourMinute True h m+      _ -> Nothing+  }++ruleHHMMSS :: Rule+ruleHHMMSS = Rule+  { name = "hh:mm:ss"+  , pattern = [regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++ruleMilitaryAMPM :: Rule+ruleMilitaryAMPM = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):Token RegexMatch (GroupMatch (ap:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleTODAMPM :: Rule+ruleTODAMPM = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(in the )?([ap])(\\s|\\.)?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (_:ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleHONumeral :: Rule+ruleHONumeral = Rule+  { name = "<hour-of-day> <integer>"+  , pattern =+    [ Predicate $ liftM2 (&&) isNotLatent isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHODHalf :: Rule+ruleHODHalf = Rule+  { name = "<hour-of-day> half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "half"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHODQuarter :: Rule+ruleHODQuarter = Rule+  { name = "<hour-of-day> quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(a|one)? ?quarter"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleNumeralToHOD :: Rule+ruleNumeralToHOD = Rule+  { name = "<integer> to|till|before <hour-of-day>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "to|till|before|of"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHalfToHOD :: Rule+ruleHalfToHOD = Rule+  { name = "half to|till|before <hour-of-day>"+  , pattern =+    [ regex "half (to|till|before|of)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleQuarterToHOD :: Rule+ruleQuarterToHOD = Rule+  { name = "quarter to|till|before <hour-of-day>"+  , pattern =+    [ regex "(a|one)? ?quarter (to|till|before|of)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleNumeralAfterHOD :: Rule+ruleNumeralAfterHOD = Rule+  { name = "integer after|past <hour-of-day>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "after|past"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesAfter n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHalfAfterHOD :: Rule+ruleHalfAfterHOD = Rule+  { name = "half after|past <hour-of-day>"+  , pattern =+    [ regex "half (after|past)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 30 td+      _ -> Nothing+  }++ruleQuarterAfterHOD :: Rule+ruleQuarterAfterHOD = Rule+  { name = "quarter after|past <hour-of-day>"+  , pattern =+    [ regex "(a|one)? ?quarter (after|past)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 15 td+      _ -> Nothing+  }++ruleHalfHOD :: Rule+ruleHalfHOD = Rule+  { name = "half <integer> (UK style hour-of-day)"+  , pattern =+    [ regex "half"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 30 td+      _ -> Nothing+  }++ruleMMDDYYYY :: Rule+ruleMMDDYYYY = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [regex "(0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])[-/](\\d{2,4})"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleYYYYMMDD :: Rule+ruleYYYYMMDD = Rule+  { name = "yyyy-mm-dd"+  , pattern = [regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleMMDD :: Rule+ruleMMDD = Rule+  { name = "mm/dd"+  , pattern = [regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleNoonMidnightEOD :: Rule+ruleNoonMidnightEOD = Rule+  { name = "noon|midnight|EOD|end of day"+  , pattern = [regex "(noon|midni(ght|te)|(the )?(EOD|end of (the )?day))"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> tt . hour False $+        if match == "noon" then 12 else 0+      _ -> Nothing+  }++rulePartOfDays :: Rule+rulePartOfDays = Rule+  { name = "part of days"+  , pattern = [regex "(morning|after ?noo?n|evening|night|(at )?lunch)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) ->+        let td = interval TTime.Open $ case Text.toLower match of+              "morning"  -> (hour False 4, hour False 12)+              "evening"  -> (hour False 18, hour False 0)+              "night"    -> (hour False 18, hour False 0)+              "lunch"    -> (hour False 12, hour False 14)+              "at lunch" -> (hour False 12, hour False 14)+              _          -> (hour False 12, hour False 19)+          in tt . partOfDay $ mkLatent td+      _ -> Nothing+  }++ruleEarlyMorning :: Rule+ruleEarlyMorning = Rule+  { name = "early morning"+  , pattern =+    [ regex "early ((in|hours of) the )?morning"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 4, hour False 9)+  }++rulePODIn :: Rule+rulePODIn = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "(in|during)( the)?"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++rulePODThis :: Rule+rulePODThis = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "this"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay . notLatent <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern = [regex "toni(ght|gth|te)"]+  , prod = \_ ->+      let today = cycleNth TG.Day 0+          evening = interval TTime.Open (hour False 18, hour False 0) in+        Token Time . partOfDay . notLatent <$> intersect today evening+  }++ruleAfterPartofday :: Rule+ruleAfterPartofday = Rule+  { name = "after lunch/work/school"+  , pattern =+    [ regex "after[\\s-]?(lunch|work|school)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        pair <- case Text.toLower match of+          "lunch"  -> Just (hour False 13, hour False 17)+          "work"   -> Just (hour False 17, hour False 21)+          "school" -> Just (hour False 15, hour False 21)+          _        -> Nothing+        Token Time . partOfDay . notLatent <$>+          intersect (cycleNth TG.Day 0) (interval TTime.Open pair)+      _ -> Nothing+  }++-- Since part of days are latent, general time intersection is blocked+ruleTimePOD :: Rule+ruleTimePOD = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token Time pod:_) -> Token Time <$> intersect pod td+      _ -> Nothing+  }++rulePODofTime :: Rule+rulePODofTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "of"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time pod:_:Token Time td:_) -> Token Time <$> intersect pod td+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern = [regex "(week(\\s|-)?end|wkend)"]+  , prod = \_ -> do+      fri <- intersect (dayOfWeek 5) (hour False 18)+      mon <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (fri, mon)+  }++ruleSeasons :: Rule+ruleSeasons = Rule+  { name = "seasons"+  , pattern = [regex "(summer|fall|autumn|winter|spring)"]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> do+        start <- case Text.toLower match of+          "summer" -> Just $ monthDay 6 21+          "fall"   -> Just $ monthDay 9 23+          "autumn" -> Just $ monthDay 9 23+          "winter" -> Just $ monthDay 12 21+          "spring" -> Just $ monthDay 3 20+          _ -> Nothing+        end <- case Text.toLower match of+          "summer" -> Just $ monthDay 9 23+          "fall"   -> Just $ monthDay 12 21+          "autumn" -> Just $ monthDay 12 21+          "winter" -> Just $ monthDay 3 20+          "spring" -> Just $ monthDay 6 21+          _ -> Nothing+        tt $ interval TTime.Open (start, end)+      _ -> Nothing++  }++ruleTODPrecision :: Rule+ruleTODPrecision = Rule+  { name = "<time-of-day> sharp|exactly"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(sharp|exactly|-?ish|approximately)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++rulePrecisionTOD :: Rule+rulePrecisionTOD = Rule+  { name = "about|exactly <time-of-day>"+  , pattern =+    [ regex "(about|around|approximately|exactly)"+    , Predicate $ isGrainFinerThan TG.Year+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleIntervalMonthDDDD :: Rule+ruleIntervalMonthDDDD = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ Predicate isAMonth+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|to|th?ru|through|(un)?til(l)?"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      ( Token Time td+       :Token RegexMatch (GroupMatch (d1:_))+       :_+       :Token RegexMatch (GroupMatch (d2:_))+       :_) -> do+        dd1 <- parseInt d1+        dd2 <- parseInt d2+        dom1 <- intersect (dayOfMonth dd1) td+        dom2 <- intersect (dayOfMonth dd2) td+        tt $ interval TTime.Closed (dom1, dom2)+      _ -> Nothing+  }++-- Blocked for :latent time. May need to accept certain latents only, like hours+ruleIntervalDash :: Rule+ruleIntervalDash = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|to|th?ru|through|(un)?til(l)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleIntervalFrom :: Rule+ruleIntervalFrom = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "from"+    , dimension Time+    , regex "\\-|to|th?ru|through|(un)?til(l)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleIntervalBetween :: Rule+ruleIntervalBetween = Rule+  { name = "between <time> and <time>"+  , pattern =+    [ regex "between"+    , dimension Time+    , regex "and"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++-- Specific for time-of-day, to help resolve ambiguities+ruleIntervalTODDash :: Rule+ruleIntervalTODDash = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isNotLatent isATimeOfDay+    , regex "\\-|:|to|th?ru|through|(un)?til(l)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleIntervalTODFrom :: Rule+ruleIntervalTODFrom = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(later than|from|(in[\\s-])?between)"+    , Predicate isATimeOfDay+    , regex "((but )?before)|\\-|to|th?ru|through|(un)?til(l)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++-- We can't take generic TOD (e.g. "6:30am - 9pm").+-- Those are handled by other rules.+ruleIntervalTODAMPM :: Rule+ruleIntervalTODAMPM = Rule+ { name = "hh(:mm) - <time-of-day> am|pm"+ , pattern =+   [ regex "(?:from )?((?:[01]?\\d)|(?:2[0-3]))([:.]([0-5]\\d))?"+   , regex "\\-|:|to|th?ru|through|(un)?til(l)?"+   , Predicate isATimeOfDay+   , regex "(in the )?([ap])(\\s|\\.)?m?\\.?"+   ]+ , prod = \tokens -> case tokens of+     (Token RegexMatch (GroupMatch (hh:_:mm:_)):+      _:+      Token Time td2:+      Token RegexMatch (GroupMatch (_:ap:_)):+      _) -> do+       h <- parseInt hh+       let ampm = Text.toLower ap == "a"+           td1 = case parseInt mm of+             Just m -> hourMinute True h m+             Nothing -> hour True h+       tt $+         interval TTime.Closed (timeOfDayAMPM td1 ampm, timeOfDayAMPM td2 ampm)+     _ -> Nothing+ }++ruleIntervalTODBetween :: Rule+ruleIntervalTODBetween = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "between"+    , Predicate isATimeOfDay+    , regex "and"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleIntervalBy :: Rule+ruleIntervalBy = Rule+  { name = "by <time>"+  , pattern =+    [ regex "by"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Open (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleIntervalByTheEndOf :: Rule+ruleIntervalByTheEndOf = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "by (the )?end of"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleIntervalUntilTOD :: Rule+ruleIntervalUntilTOD = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "(anytime |sometimes? )?(before|(un)?til(l)?|through|up to)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleIntervalAfterTOD :: Rule+ruleIntervalAfterTOD = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "(anytime |sometimes? )?after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleIntervalSinceTOD :: Rule+ruleIntervalSinceTOD = Rule+  { name = "since <time-of-day>"+  , pattern =+    [ regex "since"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++daysOfWeek :: [(Text, String)]+daysOfWeek =+  [ ( "Monday"   , "monday|mon\\.?"         )+  , ( "Tuesday"  , "tuesday|tues?\\.?"      )+  , ( "Wednesday", "wed?nesday|wed\\.?"     )+  , ( "Thursday" , "thursday|thu(rs?)?\\.?" )+  , ( "Friday"   , "friday|fri\\.?"         )+  , ( "Saturday" , "saturday|sat\\.?"       )+  , ( "Sunday"   , "sunday|sun\\.?"         )+  ]++ruleDaysOfWeek :: [Rule]+ruleDaysOfWeek = zipWith go daysOfWeek [1..7]+  where+    go (name, regexPattern) i = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> tt $ dayOfWeek i+      }++months :: [(Text, String)]+months =+  [ ( "January"  , "january|jan\\.?"     )+  , ( "February" , "february|feb\\.?"    )+  , ( "March"    , "march|mar\\.?"       )+  , ( "April"    , "april|apr\\.?"       )+  , ( "May"      , "may"                 )+  , ( "June"     , "june|jun\\.?"        )+  , ( "July"     , "july|jul\\.?"        )+  , ( "August"   , "august|aug\\.?"      )+  , ( "September", "september|sept?\\.?" )+  , ( "October"  , "october|oct\\.?"     )+  , ( "November" , "november|nov\\.?"    )+  , ( "December" , "december|dec\\.?"    )+  ]++ruleMonths :: [Rule]+ruleMonths = zipWith go months [1..12]+  where+    go (name, regexPattern) i = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> tt $ month i+      }++usHolidays :: [(Text, String, Int, Int)]+usHolidays =+  [ ( "Christmas"       , "(xmas|christmas)( day)?"         , 12, 25 )+  , ( "Christmas Eve"   , "(xmas|christmas)( day)?('s)? eve", 12, 24 )+  , ( "New Year's Eve"  , "new year'?s? eve"                , 12, 31 )+  , ( "New Year's Day"  , "new year'?s?( day)?"             , 1 , 1  )+  , ( "Valentine's Day" , "valentine'?s?( day)?"            , 2 , 14 )+  , ( "Independence Day", "independence day"                , 7 , 4  )+  , ( "Halloween"       , "hall?owe?en( day)?"              , 10, 31 )+  ]++ruleUSHolidays :: [Rule]+ruleUSHolidays = map go usHolidays+  where+    go (name, regexPattern, m, d) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> tt $ monthDay m d+      }++moreUSHolidays :: [(Text, String, Int, Int, Int)]+moreUSHolidays =+  [ ( "Martin Luther King's Day" -- Third Monday of January+    , "(MLK|Martin Luther King,?)( Jr.?| Junior)? day"+    , 3, 1, 1+    )+  , ( "Father's Day" -- Third Sunday of June+    , "father'?s?'? day"+    , 2, 7, 6+    )+  , ( "Mother's Day" -- Second Sunday of May+    , "mother'?s?'? day"+    , 1, 7, 5+    )+  , ( "Thanksgiving Day" -- Fourth Thursday of November+    , "thanks?giving( day)?"+    , 4, 4, 11+    )+  , ( "Black Friday" -- Fourth Friday of November+    , "black frid?day"+    , 4, 5, 11+    )+  ,  ( "Labor Day" -- First Monday of September+     , "labor day"+     , 1, 1, 9+     )+  ]++ruleMoreUSHolidays :: [Rule]+ruleMoreUSHolidays = map go moreUSHolidays+  where+    go (name, regexPattern, n, dow, m) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> tt $ nthDOWOfMonth n dow m+      }++-- Last Monday of May+ruleMemorialDay :: Rule+ruleMemorialDay = Rule+  { name = "Memorial Day"+  , pattern = [regex "memorial day"]+  , prod = \_ -> tt $ predLastOf (dayOfWeek 1) (month 5)+  }++-- Long weekend before the last Monday of May+ruleMemorialDayWeekend :: Rule+ruleMemorialDayWeekend = Rule+  { name = "Memorial Day Weekend"+  , pattern = [regex "memorial day week(\\s|-)?end"]+  , prod = \_ ->+      tt . longWEBefore $ predLastOf (dayOfWeek 1) (month 5)+  }++-- Long weekend before the first Monday of September+ruleLaborDayWeekend :: Rule+ruleLaborDayWeekend = Rule+  { name = "Labor Day weekend"+  , pattern = [regex "labor day week(\\s|-)?end"]+  , prod = \_ -> tt . longWEBefore $ nthDOWOfMonth 1 1 9+  }++ruleCycleThisLastNext :: Rule+ruleCycleThisLastNext = Rule+  { name = "this|last|next <cycle>"+  , pattern =+    [ regex "(this|current|coming|next|the following|last|past|previous)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):Token TimeGrain grain:_) ->+        case Text.toLower match of+          "this"          -> tt $ cycleNth grain 0+          "coming"        -> tt $ cycleNth grain 0+          "current"       -> tt $ cycleNth grain 0+          "last"          -> tt . cycleNth grain $ - 1+          "past"          -> tt . cycleNth grain $ - 1+          "previous"      -> tt . cycleNth grain $ - 1+          "next"          -> tt $ cycleNth grain 1+          "the following" -> tt $ cycleNth grain 1+          _ -> Nothing+      _ -> Nothing+  }++ruleCycleTheAfterBeforeTime :: Rule+ruleCycleTheAfterBeforeTime = Rule+  { name = "the <cycle> after|before <time>"+  , pattern =+    [ regex "the"+    , dimension TimeGrain+    , regex "(after|before)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (  _+       : Token TimeGrain grain+       : Token RegexMatch (GroupMatch (match:_))+       : Token Time td+       : _) ->+        let n = if match == "after" then 1 else - 1 in+          tt $ cycleNthAfter False grain n td+      _ -> Nothing+  }++ruleCycleAfterBeforeTime :: Rule+ruleCycleAfterBeforeTime = Rule+  { name = "<cycle> after|before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(after|before)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:Token RegexMatch (GroupMatch (match:_)):Token Time td:_) ->+        let n = if match == "after" then 1 else - 1 in+          tt $ cycleNthAfter False grain n td+      _ -> Nothing+  }++ruleCycleLastNextN :: Rule+ruleCycleLastNextN = Rule+  { name = "last|next n <cycle>"+  , pattern =+    [ regex "((last|past)|(next))"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleN True grain $ if match == "next" then n else - n+      _ -> Nothing+  }++ruleCycleOrdinalOfTime :: Rule+ruleCycleOrdinalOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "of|in|from"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleCycleTheOrdinalOfTime :: Rule+ruleCycleTheOrdinalOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "of|in|from"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleCycleTheOfTime :: Rule+ruleCycleTheOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ regex "the"+    , dimension TimeGrain+    , regex "of"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleCycleOrdinalAfterTime :: Rule+ruleCycleOrdinalAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleCycleTheOrdinalAfterTime :: Rule+ruleCycleTheOrdinalAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleCycleOrdinalQuarter :: Rule+ruleCycleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleCycleTheOrdinalQuarter :: Rule+ruleCycleTheOrdinalQuarter = Rule+  { name = "the <ordinal> quarter"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleCycleOrdinalQuarterYear :: Rule+ruleCycleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (n - 1) td+      _ -> Nothing+  }++ruleDurationInWithinAfter :: Rule+ruleDurationInWithinAfter = Rule+  { name = "in|within|after <duration>"+  , pattern =+    [ regex "(in|within|after)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       Token Duration dd:+       _) -> case Text.toLower match of+         "within" -> tt $+           interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+         "after" -> tt . withDirection TTime.After $ inDuration dd+         "in" -> tt $ inDuration dd+         _ -> Nothing+      _ -> Nothing+  }++ruleDurationHenceAgo :: Rule+ruleDurationHenceAgo = Rule+  { name = "<duration> hence|ago"+  , pattern =+    [ dimension Duration+    , regex "(hence|ago)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> case Text.toLower match of+        "ago" -> tt $ durationAgo dd+        _ -> tt $ inDuration dd+      _ -> Nothing+  }++ruleInNumeral :: Rule+ruleInNumeral = Rule+  { name = "in <number> (implicit minutes)"+  , pattern =+    [ regex "in"+    , Predicate $ isIntegerBetween 0 60+    ]+  , prod = \tokens -> case tokens of+      (_:Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        tt . inDuration . duration TG.Minute $ floor v+      _ -> Nothing+  }++ruleDurationAfterBeforeTime :: Rule+ruleDurationAfterBeforeTime = Rule+  { name = "<duration> after|before|from <time>"+  , pattern =+    [ dimension Duration+    , regex "(after|before|from)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:+       Token RegexMatch (GroupMatch (match:_)):+       Token Time td:+       _) -> case Text.toLower match of+         "before" -> tt $ durationBefore dd td+         _        -> tt $ durationAfter dd td+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleIntersect+  , ruleIntersectOf+  , ruleAbsorbOnTime+  , ruleAbsorbOnADOW+  , ruleAbsorbInMonth+  , ruleAbsorbCommaTOD+  , ruleNextDOW+  , ruleThisTime+  , ruleNextTime+  , ruleLastTime+  , ruleTimeBeforeLastAfterNext+  , ruleLastDOWOfTime+  , ruleLastCycleOfTime+  , ruleNthTimeOfTime+  , ruleTheNthTimeOfTime+  , ruleNthTimeAfterTime+  , ruleTheNthTimeAfterTime+  , ruleYear+  , ruleYearPastLatent+  , ruleYearFutureLatent+  , ruleTheDOMNumeral+  , ruleTheDOMOrdinal+  , ruleDOMLatent+  , ruleNamedDOMOrdinal+  , ruleMonthDOMNumeral+  , ruleDOMMonth+  , ruleDOMOfMonth+  , ruleDOMOrdinalMonthYear+  , ruleIdesOfMonth+  , ruleTODLatent+  , ruleAtTOD+  , ruleTODOClock+  , ruleHHMM+  , ruleHHMMLatent+  , ruleHHMMSS+  , ruleMilitaryAMPM+  , ruleTODAMPM+  , ruleHONumeral+  , ruleHODHalf+  , ruleHODQuarter+  , ruleNumeralToHOD+  , ruleHalfToHOD+  , ruleQuarterToHOD+  , ruleNumeralAfterHOD+  , ruleHalfAfterHOD+  , ruleQuarterAfterHOD+  , ruleHalfHOD+  , ruleMMDDYYYY+  , ruleYYYYMMDD+  , ruleMMDD+  , ruleNoonMidnightEOD+  , rulePartOfDays+  , ruleEarlyMorning+  , rulePODIn+  , rulePODThis+  , ruleTonight+  , ruleAfterPartofday+  , ruleTimePOD+  , rulePODofTime+  , ruleWeekend+  , ruleSeasons+  , ruleTODPrecision+  , rulePrecisionTOD+  , ruleIntervalMonthDDDD+  , ruleIntervalDash+  , ruleIntervalFrom+  , ruleIntervalBetween+  , ruleIntervalTODDash+  , ruleIntervalTODFrom+  , ruleIntervalTODAMPM+  , ruleIntervalTODBetween+  , ruleIntervalBy+  , ruleIntervalByTheEndOf+  , ruleIntervalUntilTOD+  , ruleIntervalAfterTOD+  , ruleIntervalSinceTOD+  , ruleMemorialDay+  , ruleMemorialDayWeekend+  , ruleLaborDayWeekend+  , ruleCycleThisLastNext+  , ruleCycleTheAfterBeforeTime+  , ruleCycleAfterBeforeTime+  , ruleCycleLastNextN+  , ruleCycleOrdinalOfTime+  , ruleCycleTheOrdinalOfTime+  , ruleCycleTheOfTime+  , ruleCycleOrdinalAfterTime+  , ruleCycleTheOrdinalAfterTime+  , ruleCycleOrdinalQuarter+  , ruleCycleTheOrdinalQuarter+  , ruleCycleOrdinalQuarterYear+  , ruleDurationInWithinAfter+  , ruleDurationHenceAgo+  , ruleDurationAfterBeforeTime+  , ruleInNumeral+  , ruleTimezone+  ]+  ++ ruleInstants+  ++ ruleDaysOfWeek+  ++ ruleMonths+  ++ ruleUSHolidays+  ++ ruleMoreUSHolidays
+ Duckling/Time/ES/Corpus.hs view
@@ -0,0 +1,416 @@+-- 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.Time.ES.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = ES}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "ahora"+             , "ya"+             , "ahorita"+             , "cuanto antes"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "hoy"+             , "en este momento"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "ayer"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "anteayer"+             , "antier"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mañana"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "pasado mañana"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lunes"+             , "lu"+             , "lun."+             , "este lunes"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lunes, 18 de febrero"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "martes"+             , "ma"+             , "ma."+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "miercoles"+             , "miércoles"+             , "mx"+             , "mié."+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "jueves"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "viernes"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "sabado"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "domingo"+             ]+  , examples (datetime (2013, 5, 5, 0, 0, 0) Day)+             [ "el 5 de mayo"+             , "el cinco de mayo"+             ]+  , examples (datetime (2013, 5, 5, 0, 0, 0) Day)+             [ "el cinco de mayo de 2013"+             , "mayo 5 del 2013"+             , "5-5-2013"+             ]+  , examples (datetime (2013, 7, 4, 0, 0, 0) Day)+             [ "el 4 de julio"+             , "el 4/7"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "el 3 de marzo"+             , "3 de marzo"+             , "el 3-3"+             ]+  , examples (datetime (2013, 4, 5, 0, 0, 0) Day)+             [ "el 5 de abril"+             , "5 de abril"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "el 1 de marzo"+             , "1 de marzo"+             , "el primero de marzo"+             , "el uno de marzo"+             , "primero de marzo"+             , "uno de marzo"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1-3-2013"+             , "1.3.2013"+             , "1/3/2013"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "el 16"+             , "16 de febrero"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "el 17"+             , "17 de febrero"+             , "17-2"+             , "el 17/2"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "el 20"+             , "20 de febrero"+             , "20/2"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "el martes que viene"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "miércoles que viene"+             , "el miércoles de la semana que viene"+             , "miercoles de la próxima semana"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "el lunes de esta semana"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "martes de esta semana"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "el miércoles de esta semana"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "esta semana"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "la semana pasada"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "la semana que viene"+             , "la proxima semana"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Month)+             [ "el pasado mes"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "el mes que viene"+             , "el proximo mes"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "el año pasado"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "este ano"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "el año que viene"+             , "el proximo ano"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "el domingo pasado"+             , "el domingo de la semana pasada"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "el martes pasado"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "a las tres de la tarde"+             , "a las tres"+             , "a las 3 pm"+             , "a las 15 horas"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "a las ocho de la tarde"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Minute)+             [ "15:00"+             , "15.00"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "medianoche"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "mediodía"+             , "las doce"+             ]+  , examples (datetime (2013, 2, 12, 12, 15, 0) Minute)+             [ "las doce y cuarto"+             ]+  , examples (datetime (2013, 2, 12, 11, 55, 0) Minute)+             [ "las doce menos cinco"+             ]+  , examples (datetime (2013, 2, 12, 12, 30, 0) Minute)+             [ "las doce y media"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "las tres de la manana"+             , "las tres en la manana"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "a las tres y quince"+             , "a las 3 y cuarto"+             , "a las tres y cuarto de la tarde"+             , "a las tres y cuarto en la tarde"+             , "15:15"+             , "15.15"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "a las tres y media"+             , "a las 3 y treinta"+             , "a las tres y media de la tarde"+             , "a las 3 y treinta del mediodía"+             , "15:30"+             , "15.30"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "las doce menos cuarto"+             , "11:45"+             , "las once y cuarenta y cinco"+             , "hoy a las doce menos cuarto"+             , "hoy a las once y cuarenta y cinco"+             ]+  , examples (datetime (2013, 2, 12, 5, 15, 0) Minute)+             [ "5 y cuarto"+             ]+  , examples (datetime (2013, 2, 12, 6, 0, 0) Hour)+             [ "6 de la mañana"+             ]+  , examples (datetime (2013, 2, 13, 11, 0, 0) Hour)+             [ "miércoles a las once de la mañana"+             ]+  , examples (datetime (2013, 2, 13, 11, 0, 0) Hour)+             [ "mañana a las once"+             , "mañana a 11"+             ]+  , examples (datetime (2014, 9, 12, 0, 0, 0) Day)+             [ "viernes, el 12 de septiembre de 2014"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "en un segundo"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "en un minuto"+             , "en 1 min"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "en 2 minutos"+             , "en dos minutos"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "en 60 minutos"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "en una hora"+             ]+  , examples (datetime (2013, 2, 12, 2, 30, 0) Minute)+             [ "hace dos horas"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "en 24 horas"+             , "en veinticuatro horas"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "en un dia"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "en 7 dias"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "en una semana"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "hace tres semanas"+             ]+  , examples (datetime (2013, 4, 12, 0, 0, 0) Day)+             [ "en dos meses"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "hace tres meses"+             ]+  , examples (datetime (2014, 2, 0, 0, 0, 0) Month)+             [ "en un ano"+             , "en 1 año"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "hace dos años"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "este verano"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "este invierno"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "Navidad"+             , "la Navidad"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "Nochevieja"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "ano nuevo"+             , "año nuevo"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "esta noche"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "mañana por la noche"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "ayer por la noche"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "este weekend"+             , "este fin de semana"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "lunes por la mañana"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "el 15 de febrero por la mañana"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "a las 8 de la tarde"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "pasados 2 segundos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "proximos 3 segundos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "pasados 2 minutos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "proximos 3 minutos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "proximas 3 horas"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "pasados 2 dias"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "proximos 3 dias"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "pasadas dos semanas"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "3 proximas semanas"+             , "3 semanas que vienen"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "pasados 2 meses"+             , "dos pasados meses"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "3 próximos meses"+             , "proximos tres meses"+             , "tres meses que vienen"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "pasados 2 anos"+             , "dos pasados años"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "3 próximos años"+             , "proximo tres años"+             , "3 años que vienen"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13 a 15 de julio"+             , "13 - 15 de julio de 2013"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 0, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 12, 21, 0, 0, 0), (2014, 1, 7, 0, 0, 0)) Day)+             [ "21 de Dic. a 6 de Ene"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 12, 7, 30, 0)) Second)+             [ "dentro de tres horas"+             ]+  , examples (datetime (2013, 2, 12, 16, 0, 0) Hour)+             [ "a las cuatro de la tarde"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "a las cuatro CET"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "jue 15"+             ]+  ]
+ Duckling/Time/ES/Rules.hs view
@@ -0,0 +1,1593 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.ES.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "lunes|lun?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "pasado\\s?ma(n|\x00f1)ana"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleHaceDuration :: Rule+ruleHaceDuration = Rule+  { name = "hace <duration>"+  , pattern =+    [ regex "hace"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "diciembre|dic\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleCeTime :: Rule+ruleCeTime = Rule+  { name = "ce <time>"+  , pattern =+    [ regex "este"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "martes|mar?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleThisDayofweek :: Rule+ruleThisDayofweek = Rule+  { name = "this <day-of-week>"+  , pattern =+    [ regex "este"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s(\x00e1|a)bado|s(\x00e1|a)b\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|al?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "julio|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "noche"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayOfMonthSt :: Rule+ruleDayOfMonthSt = Rule+  { name = "day of month (1st)"+  , pattern =+    [ regex "primero|uno|prem\\.?|1o"+    ]+  , prod = \_ -> tt $ dayOfMonth 1+  }++ruleEnDuration :: Rule+ruleEnDuration = Rule+  { name = "en <duration>"+  , pattern =+    [ regex "en"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "(hoy)|(en este momento)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleUltimoDayofweekDeTime :: Rule+ruleUltimoDayofweekDeTime = Rule+  { name = "ultimo <day-of-week> de <time>"+  , pattern =+    [ regex "(\x00fa|u)ltimo"+    , Predicate isADayOfWeek+    , regex "de|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleEntreDatetimeEtDatetimeInterval :: Rule+ruleEntreDatetimeEtDatetimeInterval = Rule+  { name = "entre <datetime> et <datetime> (interval)"+  , pattern =+    [ regex "entre"+    , dimension Time+    , regex "y"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleHhhmmTimeofday :: Rule+ruleHhhmmTimeofday = Rule+  { name = "hh(:|.|h)mm (time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:h\\.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "jueves|jue|jue\\."+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleElDayofmonthDeNamedmonth :: Rule+ruleElDayofmonthDeNamedmonth = Rule+  { name = "el <day-of-month> de <named-month>"+  , pattern =+    [ regex "el"+    , Predicate isDOMInteger+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNPasadosCycle :: Rule+ruleNPasadosCycle = Rule+  { name = "n pasados <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "pasad(a|o)s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleElProximoCycle :: Rule+ruleElProximoCycle = Rule+  { name = "el proximo <cycle> "+  , pattern =+    [ regex "(el|los|la|las) ?"+    , regex "pr(\x00f3|o)xim(o|a)s?|siguientes?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++rulePasadosNCycle :: Rule+rulePasadosNCycle = Rule+  { name = "pasados n <cycle>"+  , pattern =+    [ regex "pasad(a|o)s?"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleElDayofmonthNonOrdinal :: Rule+ruleElDayofmonthNonOrdinal = Rule+  { name = "el <day-of-month> (non ordinal)"+  , pattern =+    [ regex "el"+    , Predicate $ isIntegerBetween 1 31+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "primavera"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "mediod(\x00ed|i)a"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleProximasNCycle :: Rule+ruleProximasNCycle = Rule+  { name = "proximas n <cycle>"+  , pattern =+    [ regex "pr(\x00f3|o)xim(o|a)s?"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleNochevieja :: Rule+ruleNochevieja = Rule+  { name = "Nochevieja"+  , pattern =+    [ regex "nochevieja"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "anteayer|antes de (ayer|anoche)|antier"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleHourofdayMinusIntegerAsRelativeMinutes :: Rule+ruleHourofdayMinusIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> minus <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "menos\\s?"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayMinusIntegerAsRelativeMinutes2 :: Rule+ruleHourofdayMinusIntegerAsRelativeMinutes2 = Rule+  { name = "<hour-of-day> minus <integer> (as relative minutes) minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "menos\\s?"+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayMinusQuarter :: Rule+ruleHourofdayMinusQuarter = Rule+  { name = "<hour-of-day> minus quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "menos\\s? cuarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> do+        t <- minutesBefore 15 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayMinusHalf :: Rule+ruleHourofdayMinusHalf = Rule+  { name = "<hour-of-day> minus half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "menos\\s? media"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> do+        t <- minutesBefore 30 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayMinusThreeQuarter :: Rule+ruleHourofdayMinusThreeQuarter = Rule+  { name = "<hour-of-day> minus three quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "menos\\s? (3|tres) cuartos?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> do+        t <- minutesBefore 45 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes2 :: Rule+ruleHourofdayIntegerAsRelativeMinutes2 = Rule+  { name = "<hour-of-day> <integer> (as relative minutes) minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "cuarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "media"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHourofdayThreeQuarter :: Rule+ruleHourofdayThreeQuarter = Rule+  { name = "<hour-of-day> three quarters (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(3|tres) cuartos?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 45+      _ -> Nothing+  }++ruleHourofdayAndRelativeMinutes :: Rule+ruleHourofdayAndRelativeMinutes = Rule+  { name = "<hour-of-day> and <relative minutes>"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "y"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayAndRelativeMinutes2 :: Rule+ruleHourofdayAndRelativeMinutes2 = Rule+  { name = "<hour-of-day> and <relative minutes> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "y"+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayAndQuarter :: Rule+ruleHourofdayAndQuarter = Rule+  { name = "<hour-of-day> and quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "y cuarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayAndHalf :: Rule+ruleHourofdayAndHalf = Rule+  { name = "<hour-of-day> and half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "y media"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHourofdayAndThreeQuarter :: Rule+ruleHourofdayAndThreeQuarter = Rule+  { name = "<hour-of-day> and 3 quarters"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "y (3|tres) cuartos?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 45+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "enero|ene\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleInThePartofday :: Rule+ruleInThePartofday = Rule+  { name = "in the <part-of-day>"+  , pattern =+    [ regex "(a|en|de|por) la"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleDelYear :: Rule+ruleDelYear = Rule+  { name = "del <year>"+  , pattern =+    [ regex "del( a(\x00f1|n)o)?"+    , Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "marzo|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd[/-]mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[/-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        d <- parseInt m1+        m <- parseInt m2+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "tarde"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "abril|abr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleMidnight :: Rule+ruleMidnight = Rule+  { name = "midnight"+  , pattern =+    [ regex "medianoche"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleAnoNuevo :: Rule+ruleAnoNuevo = Rule+  { name = "ano nuevo"+  , pattern =+    [ regex "a(n|\x00f1)o nuevo"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "viernes|vie|vie\\."+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDdddMonthinterval :: Rule+ruleDdddMonthinterval = Rule+  { name = "dd-dd <month>(interval)"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|al?"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       _:+       Token Time td:+       _) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        from <- intersect (dayOfMonth d1) td+        to <- intersect (dayOfMonth d2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "febrero|feb\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleNamedmonthnameddayPast :: Rule+ruleNamedmonthnameddayPast = Rule+  { name = "<named-month|named-day> past"+  , pattern =+    [ dimension Time+    , regex "pasad(o|a)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "invierno"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "verano"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleRightNow :: Rule+ruleRightNow = Rule+  { name = "right now"+  , pattern =+    [ regex "ahor(it)?a|ya|en\\s?seguida|cuanto antes"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleDimTimeDeLaTarde :: Rule+ruleDimTimeDeLaTarde = Rule+  { name = "<dim time> de la tarde"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(a|en|de) la tarde"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let tarde = interval TTime.Open (hour False 12, hour False 21)+        in Token Time <$> intersect td (mkLatent $ partOfDay tarde)+      _ -> Nothing+  }++ruleIntegerInThePartofday :: Rule+ruleIntegerInThePartofday = Rule+  { name = "<integer> in the <part-of-day>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "(a|en|de|por) la"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNCycleProximoqueViene :: Rule+ruleNCycleProximoqueViene = Rule+  { name = "n <cycle> (proximo|que viene)"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "(pr(\x00f3|o)xim(o|a)s?|que vienen?|siguientes?)"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleNamedmonthnameddayNext :: Rule+ruleNamedmonthnameddayNext = Rule+  { name = "<named-month|named-day> next"+  , pattern =+    [ dimension Time+    , regex "que vienen?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTimeofdayPartofday :: Rule+ruleTimeofdayPartofday = Rule+  { name = "<time-of-day> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleDimTimeDeLaManana :: Rule+ruleDimTimeDeLaManana = Rule+  { name = "<dim time> de la manana"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(a|en|de) la ma(\x00f1|n)ana"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let manana = interval TTime.Open (hour False 0, hour False 12)+        in Token Time <$> intersect td (mkLatent $ partOfDay manana)+      _ -> Nothing+  }++ruleDeDatetimeDatetimeInterval :: Rule+ruleDeDatetimeDatetimeInterval = Rule+  { name = "de <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "del?"+    , dimension Time+    , regex "\\-|al?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleNthTimeDeTime2 :: Rule+ruleNthTimeDeTime2 = Rule+  { name = "nth <time> de <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension Time+    , regex "de|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "junio|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleDentroDeDuration :: Rule+ruleDentroDeDuration = Rule+  { name = "dentro de <duration>"+  , pattern =+    [ regex "dentro de"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $+          interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "agosto|ago\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "week[ -]?end|fin de semana"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , regex "del? ?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (v - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayHoras :: Rule+ruleTimeofdayHoras = Rule+  { name = "<time-of-day> horas"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "h\\.?(ora)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNavidad :: Rule+ruleNavidad = Rule+  { name = "Navidad"+  , pattern =+    [ regex "(la )?navidad"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleElCycleAntesTime :: Rule+ruleElCycleAntesTime = Rule+  { name = "el <cycle> antes <time>"+  , pattern =+    [ regex "l[ea']? ?"+    , dimension TimeGrain+    , regex "antes de"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleTwoTimeTokensSeparatedBy :: Rule+ruleTwoTimeTokensSeparatedBy = Rule+  { name = "two time tokens separated by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "ma(\x00f1|n)ana"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleALasHourmintimeofday :: Rule+ruleALasHourmintimeofday = Rule+  { name = "a las <hour-min>(time-of-day)"+  , pattern =+    [ regex "((al?)( las?)?|las?)"+    , Predicate isATimeOfDay+    , regex "horas?"+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "est(e|a)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleLaCyclePasado :: Rule+ruleLaCyclePasado = Rule+  { name = "la <cycle> pasado"+  , pattern =+    [ regex "(el|los|la|las) ?"+    , dimension TimeGrain+    , regex "pasad(a|o)s?|(u|\x00fa)ltim[ao]s?"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "ayer"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "oto(\x00f1|n)o"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleDayofweekDayofmonth :: Rule+ruleDayofweekDayofmonth = Rule+  { name = "<day-of-week> <day-of-month>"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleDayofmonthDeNamedmonth :: Rule+ruleDayofmonthDeNamedmonth = Rule+  { name = "<day-of-month> de <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleEntreDdEtDdMonthinterval :: Rule+ruleEntreDdEtDdMonthinterval = Rule+  { name = "entre dd et dd <month>(interval)"+  , pattern =+    [ regex "entre( el)?"+    , regex "(0?[1-9]|[12]\\d|3[01])"+    , regex "y( el)?"+    , regex "(0?[1-9]|[12]\\d|3[01])"+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       _:+       Token Time td:+       _) -> do+        v1 <- parseInt m1+        v2 <- parseInt m2+        from <- intersect (dayOfMonth v1) td+        to <- intersect (dayOfMonth v2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedmonthDayofmonth :: Rule+ruleNamedmonthDayofmonth = Rule+  { name = "<named-month> <day-of-month>"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mayo?\\.?"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "domingo|dom\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleElTime :: Rule+ruleElTime = Rule+  { name = "el <time>"+  , pattern =+    [ regex "d?el"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "octubre|oct\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleEsteenUnCycle :: Rule+ruleEsteenUnCycle = Rule+  { name = "este|en un <cycle>"+  , pattern =+    [ regex "(est(e|a|os)|en (el|los|la|las) ?)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleNProximasCycle :: Rule+ruleNProximasCycle = Rule+  { name = "n proximas <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "pr(\x00f3|o)xim(o|a)s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleLaPasadoCycle :: Rule+ruleLaPasadoCycle = Rule+  { name = "la pasado <cycle>"+  , pattern =+    [ regex "(el|los|la|las) ?"+    , regex "pasad(a|o)s?|(u|\x00fa)ltim[ao]s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleALasTimeofday :: Rule+ruleALasTimeofday = Rule+  { name = "a las <time-of-day>"+  , pattern =+    [ regex "(al?)( las?)?|las?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd[/-.]mm[/-.]yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\./-](0?[1-9]|1[0-2])[\\./-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        d <- parseInt m1+        m <- parseInt m2+        y <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "noviembre|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt . cycleNthAfter False TG.Quarter (v - 1)+          $ cycleNth TG.Year 0+      _ -> Nothing+  }++ruleElCycleProximoqueViene :: Rule+ruleElCycleProximoqueViene = Rule+  { name = "el <cycle> (proximo|que viene)"+  , pattern =+    [ regex "(el|los|la|las) ?"+    , dimension TimeGrain+    , regex "(pr(\x00f3|o)xim(o|a)s?|que vienen?|siguientes?)"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleElCycleProximoqueVieneTime :: Rule+ruleElCycleProximoqueVieneTime = Rule+  { name = "el <cycle> proximo|que viene <time>"+  , pattern =+    [ regex "(el|los|la|las)"+    , dimension TimeGrain+    , regex "(pr(\x00f3|o)xim(o|a)s?|que vienen?|siguientes?)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleDelMedioda :: Rule+ruleDelMedioda = Rule+  { name = "del mediodía"+  , pattern =+    [ regex "del mediod(i|\x00ed)a"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 17+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mi(e|\x00e9)\\.?(rcoles)?|mx|mier?\\."+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleIntersectByDe :: Rule+ruleIntersectByDe = Rule+  { name = "intersect by `de`"+  , pattern =+    [ Predicate isNotLatent+    , regex "de"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "ma(n|\x00f1)ana"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleNthTimeDeTime :: Rule+ruleNthTimeDeTime = Rule+  { name = "nth <time> de <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "de|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "septiembre|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleALasHourmintimeofday+  , ruleALasTimeofday+  , ruleAfternoon+  , ruleAnoNuevo+  , ruleCeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayOfMonthSt+  , ruleDayofmonthDeNamedmonth+  , ruleDayofweekDayofmonth+  , ruleDdddMonthinterval+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDeDatetimeDatetimeInterval+  , ruleDelMedioda+  , ruleDelYear+  , ruleDentroDeDuration+  , ruleDimTimeDeLaManana+  , ruleDimTimeDeLaTarde+  , ruleElCycleAntesTime+  , ruleElCycleProximoqueViene+  , ruleElCycleProximoqueVieneTime+  , ruleElDayofmonthDeNamedmonth+  , ruleElDayofmonthNonOrdinal+  , ruleElProximoCycle+  , ruleElTime+  , ruleEnDuration+  , ruleEntreDatetimeEtDatetimeInterval+  , ruleEntreDdEtDdMonthinterval+  , ruleEsteenUnCycle+  , ruleEvening+  , ruleHaceDuration+  , ruleHhhmmTimeofday+  , ruleHourofdayAndRelativeMinutes+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayMinusIntegerAsRelativeMinutes+  , ruleInThePartofday+  , ruleIntegerInThePartofday+  , ruleIntersect+  , ruleIntersectByDe+  , ruleLaCyclePasado+  , ruleLaPasadoCycle+  , ruleMidnight+  , ruleMorning+  , ruleNCycleProximoqueViene+  , ruleNPasadosCycle+  , ruleNProximasCycle+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonth+  , ruleNamedmonthnameddayNext+  , ruleNamedmonthnameddayPast+  , ruleNavidad+  , ruleNochevieja+  , ruleNoon+  , ruleNow+  , ruleNthTimeDeTime+  , ruleNthTimeDeTime2+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePasadosNCycle+  , ruleProximasNCycle+  , ruleRightNow+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleThisDayofweek+  , ruleThisPartofday+  , ruleTimeofdayAmpm+  , ruleTimeofdayHoras+  , ruleTimeofdayLatent+  , ruleTimeofdayPartofday+  , ruleTomorrow+  , ruleTwoTimeTokensSeparatedBy+  , ruleUltimoDayofweekDeTime+  , ruleWeekend+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleHourofdayAndThreeQuarter+  , ruleHourofdayAndHalf+  , ruleHourofdayAndQuarter+  , ruleHourofdayAndRelativeMinutes2+  , ruleHourofdayThreeQuarter+  , ruleHourofdayHalf+  , ruleHourofdayQuarter+  , ruleHourofdayIntegerAsRelativeMinutes2+  , ruleHourofdayMinusThreeQuarter+  , ruleHourofdayMinusHalf+  , ruleHourofdayMinusQuarter+  , ruleHourofdayMinusIntegerAsRelativeMinutes2+  , ruleTimezone+  ]
+ Duckling/Time/FR/Corpus.hs view
@@ -0,0 +1,774 @@+-- 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.Time.FR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "maintenant"+             , "tout de suite"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "aujourd'hui"+             , "ce jour"+             , "dans la journée"+             , "en ce moment"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "hier"+             , "le jour d'avant"+             , "le jour précédent"+             , "la veille"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "avant-hier"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "demain"+             , "jour suivant"+             , "le jour d'après"+             , "le lendemain"+             , "un jour après"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "après-demain"+             , "le lendemain du 13 février"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lundi"+             , "lun."+             , "ce lundi"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lundi 18 février"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "mardi"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercredi 13 février"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "jeudi"+             , "deux jours plus tard"+             , "deux jours après"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "vendredi"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "samedi"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "dimanche"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "le 1er mars"+             , "premier mars"+             , "le 1 mars"+             , "vendredi 1er mars"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "le premier mars 2013"+             , "1/3/2013"+             , "2013-03-01"+             ]+  , examples (datetime (2013, 3, 2, 0, 0, 0) Day)+             [ "le 2 mars"+             , "2 mars"+             , "le 2/3"+             ]+  , examples (datetime (2013, 3, 2, 5, 0, 0) Hour)+             [ "le 2 mars à 5h"+             , "2 mars à 5h"+             , "le 2/3 à 5h"+             , "le 2 mars à 5h du matin"+             , "le 2 mars vers 5h"+             , "2 mars vers 5h"+             , "2 mars à environ 5h"+             , "2 mars aux alentours de 5h"+             , "2 mars autour de 5h"+             , "le 2/3 vers 5h"+             ]+  , examples (datetime (2013, 3, 2, 0, 0, 0) Day)+             [ "le 2"+             ]+  , examples (datetime (2013, 3, 2, 5, 0, 0) Hour)+             [ "le 2 à 5h"+             , "le 2 vers 5h"+             , "le 2 à 5h du mat"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "le 3 mars"+             , "3 mars"+             , "le 3/3"+             ]+  , examples (datetime (2013, 4, 5, 0, 0, 0) Day)+             [ "le 5 avril"+             , "5 avril"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "le 3 mars 2015"+             , "3 mars 2015"+             , "3/3/2015"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "le 15 février"+             , "15 février"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15/02/2013"+             , "15 fev 2013"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "le 16"+             ]+  , examples (datetime (2013, 2, 16, 18, 0, 0) Hour)+             [ "le 16 à 18h"+             , "le 16 vers 18h"+             , "le 16 plutôt vers 18h"+             , "le 16 à 6h du soir"+             , "le 16 vers 6h du soir"+             , "le 16 vers 6h dans la soirée"+             , "samedi 16 à 18h"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "17 février"+             , "le 17 février"+             , "17/2"+             , "17/02"+             , "le 17/02"+             , "17 02"+             , "17 2"+             , "le 17 02"+             , "le 17 2"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercredi 13"+             ]+  , examples (datetime (2014, 2, 20, 0, 0, 0) Day)+             [ "20/02/2014"+             , "20/2/2014"+             , "20/02/14"+             , "le 20/02/14"+             , "le 20/2/14"+             , "20 02 2014"+             , "20 02 14"+             , "20 2 2014"+             , "20 2 14"+             , "le 20 02 2014"+             , "le 20 02 14"+             , "le 20 2 2014"+             , "le 20 2 14"+             ]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "31 octobre"+             , "le 31 octobre"+             , "31/10"+             , "le 31/10"+             , "31 10"+             , "le 31 10"+             ]+  , examples (datetime (2014, 12, 24, 0, 0, 0) Day)+             [ "24/12/2014"+             , "24/12/14"+             , "le 24/12/14"+             , "24 12 2014"+             , "24 12 14"+             , "le 24 12 2014"+             , "le 24 12 14"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lundi prochain"+             , "lundi la semaine prochaine"+             , "lundi de la semaine prochaine"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "mardi prochain"+             , "mardi suivant"+             , "mardi d'après"+             , "mardi la semaine prochaine"+             , "mardi de la semaine prochaine"+             , "mardi la semaine suivante"+             , "mardi de la semaine suivante"+             , "mardi la semaine d'après"+             , "mardi de la semaine d'après"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercredi prochain"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "mercredi suivant"+             , "mercredi d'après"+             , "mercredi la semaine prochaine"+             , "mercredi de la semaine prochaine"+             , "mercredi la semaine suivante"+             , "mercredi de la semaine suivante"+             , "mercredi la semaine d'après"+             , "mercredi de la semaine d'après"+             ]+  , examples (datetime (2013, 2, 25, 0, 0, 0) Day)+             [ "lundi en huit"+             , "lundi en 8"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "mardi en huit"+             , "mardi en 8"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "mercredi en huit"+             , "mercredi en 8"+             ]+  , examples (datetime (2013, 3, 4, 0, 0, 0) Day)+             [ "lundi en quinze"+             , "lundi en 15"+             ]+  , examples (datetime (2013, 2, 26, 0, 0, 0) Day)+             [ "mardi en quinze"+             , "mardi en 15"+             ]+  , examples (datetime (2013, 2, 27, 0, 0, 0) Day)+             [ "mercredi en quinze"+             , "mercredi en 15"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "lundi cette semaine"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "mardi cette semaine"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercredi cette semaine"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "cette semaine"+             , "dans la semaine"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "la semaine dernière"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "la semaine prochaine"+             , "la semaine suivante"+             , "la semaine qui suit"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "le mois dernier"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "le mois prochain"+             , "le mois suivant"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "l'année dernière"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "cette année"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "l'année prochaine"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "dimanche dernier"+             , "dimanche de la semaine dernière"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "3eme jour d'octobre"+             , "le 3eme jour d'octobre"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "premiere semaine d'octobre 2014"+             , "la premiere semaine d'octobre 2014"+             ]+  , examples (datetime (2013, 10, 7, 0, 0, 0) Week)+             [ "la semaine du 6 octobre"+             , "la semaine du 7 octobre"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "dernier jour d'octobre 2015"+             , "le dernier jour d'octobre 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "dernière semaine de septembre 2014"+             , "la dernière semaine de septembre 2014"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "à quinze heures"+             , "à 15 heures"+             , "à 3 heures cet après-midi"+             , "15h"+             , "15H"+             , "vers 15 heures"+             , "à environ 15 heures"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Minute)+             [ "15:00"+             , "15h00"+             , "15H00"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "minuit"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "midi"+             , "aujourd'hui à midi"+             ]+  , examples (datetime (2013, 2, 12, 12, 15, 0) Minute)+             [ "midi et quart"+             , "midi quinze"+             ]+  , examples (datetime (2013, 2, 12, 11, 55, 0) Minute)+             [ "midi moins cinq"+             ]+  , examples (datetime (2013, 2, 12, 12, 30, 0) Minute)+             [ "midi et demi"+             , "midi trente"+             ]+  , examples (datetime (2013, 2, 13, 0, 3, 0) Minute)+             [ "minuit trois"+             ]+  , examples (datetime (2013, 2, 12, 0, 3, 0) Minute)+             [ "aujourd'hui à minuit trois"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "à quinze heures quinze"+             , "à quinze heures et quinze minutes"+             , "15h passé de 15 minutes"+             , "à trois heures et quart cet après-midi"+             , "15:15"+             , "15h15"+             ]+  , examples (datetime (2013, 2, 13, 15, 15, 0) Minute)+             [ "à trois heures et quart demain après-midi"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "à quinze heures trente"+             , "à quinze heures passé de trente minutes"+             , "à trois heures et demi cet après-midi"+             , "15:30"+             , "15h30"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "midi moins le quart"+             , "11h45"+             , "onze heures trois quarts"+             , "aujourd'hui à 11h45"+             ]+  , examples (datetime (2013, 2, 13, 11, 0, 0) Hour)+             [ "mercredi à 11h"+             ]+  , examples (datetime (2013, 2, 13, 11, 0, 0) Hour)+             [ "demain à 11 heures"+             , "demain à 11H"+             ]+  , examples (datetime (2013, 2, 14, 11, 0, 0) Hour)+             [ "jeudi à 11h"+             , "après-demain à 11 heures"+             , "après-demain à 11H"+             ]+  , examples (datetime (2013, 2, 15, 12, 0, 0) Hour)+             [ "vendredi à midi"+             , "vendredi à 12h"+             ]+  , examples (datetime (2013, 2, 15, 16, 0, 0) Hour)+             [ "vendredi quinze à seize heures"+             , "vendredi 15 à 16h"+             , "vendredi quinze à 16h"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "dans une seconde"+             , "dans 1\""+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "dans une minute"+             , "dans 1 min"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "dans 2 minutes"+             , "dans deux min"+             , "dans 2'"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "dans 60 minutes"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "dans une heure"+             ]+  , examples (datetime (2013, 2, 12, 2, 30, 0) Minute)+             [ "il y a deux heures"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "dans 24 heures"+             , "dans vingt quatre heures"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "dans un jour"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "dans 7 jours"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "dans 1 semaine"+             , "dans une semaine"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "il y a trois semaines"+             ]+  , examples (datetime (2013, 4, 12, 0, 0, 0) Day)+             [ "dans deux mois"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "il y a trois mois"+             ]+  , examples (datetime (2014, 2, 0, 0, 0, 0) Month)+             [ "dans une année"+             , "dans 1 an"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "il y a deux ans"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "cet été"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "cet hiver"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "Noel"+             , "noël"+             , "jour de noel"+             ]+  , examples (datetimeInterval ((2013, 12, 24, 18, 0, 0), (2013, 12, 25, 0, 0, 0)) Hour)+             [ "le soir de noël"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "jour de l'an"+             , "nouvel an"+             , "premier janvier"+             ]+  , examples (datetime (2013, 11, 1, 0, 0, 0) Day)+             [ "la toussaint"+             , "le jour de la toussaint"+             , "la journée de la toussaint"+             , "toussaint"+             , "le jour des morts"+             ]+  , examples (datetime (2013, 5, 1, 0, 0, 0) Day)+             [ "fête du travail"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "cet après-midi"+             , "l'après-midi"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 7, 0, 0), (2013, 2, 12, 9, 0, 0)) Hour)+             [ "en début de matinée"+             , "aujourd'hui très tôt le matin"+             , "aujourd'hui tôt le matin"+             , "aujourd'hui le matin tôt"+             , "aujourd'hui le matin très tôt"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 10, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "en fin de matinée"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "après déjeuner"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 10, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "avant déjeuner"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 14, 0, 0)) Hour)+             [ "aujourd'hui pendant le déjeuner"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 17, 0, 0), (2013, 2, 12, 21, 0, 0)) Hour)+             [ "après le travail"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "dès le matin"+             , "dès la matinée"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 14, 0, 0)) Hour)+             [ "en début d'après-midi"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 17, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "en fin d'après-midi"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 6, 0, 0), (2013, 2, 12, 10, 0, 0)) Hour)+             [ "en début de journée"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 17, 0, 0), (2013, 2, 12, 21, 0, 0)) Hour)+             [ "en fin de journée"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "ce soir"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 12, 21, 0, 0)) Hour)+             [ "en début de soirée"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 21, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "en fin de soirée"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "demain soir"+             , "mercredi soir"+             , "mercredi en soirée"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "hier soir"+             , "la veille au soir"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "ce week-end"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 0, 0, 0), (2013, 2, 13, 0, 0, 0)) Day)+             [ "en début de semaine"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 15, 0, 0, 0)) Day)+             [ "en milieu de semaine"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 0, 0, 0), (2013, 2, 18, 0, 0, 0)) Day)+             [ "en fin de semaine"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "en semaine"+             ]+  , examples (datetimeInterval ((2013, 9, 6, 18, 0, 0), (2013, 9, 9, 0, 0, 0)) Hour)+             [ "le premier week-end de septembre"+             ]+  , examples (datetimeInterval ((2013, 9, 13, 18, 0, 0), (2013, 9, 16, 0, 0, 0)) Hour)+             [ "le deuxième week-end de septembre"+             ]+  , examples (datetimeInterval ((2013, 9, 27, 18, 0, 0), (2013, 9, 30, 0, 0, 0)) Hour)+             [ "le dernier week-end de septembre"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "lundi matin"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 12, 0, 0), (2013, 2, 18, 19, 0, 0)) Hour)+             [ "lundi après-midi"+             , "lundi dans l'après-midi"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 17, 0, 0), (2013, 2, 18, 19, 0, 0)) Hour)+             [ "lundi fin d'après-midi"+             , "lundi en fin d'après-midi"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "le 15 février dans la matinée"+             , "matinée du 15 février"+             , "le 15 février le matin"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 heures ce soir"+             , "8h du soir"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "3 heures du matin"+             , "3h du mat"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "2 dernières secondes"+             , "deux dernieres secondes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "3 prochaines secondes"+             , "trois prochaines secondes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "2 dernieres minutes"+             , "deux dernières minutes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "3 prochaines minutes"+             , "trois prochaines minutes"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "3 prochaines heures"+             , "3 heures suivantes"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "2 dernier jours"+             , "deux derniers jour"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "3 prochains jours"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "2 dernieres semaines"+             , "2 semaines passées"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "3 prochaines semaines"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "2 derniers mois"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "3 prochains mois"+             , "3 mois suivant"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "2 dernieres annees"+             , "2 années passées"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "3 prochaines années"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13-15 juillet"+             , "13 au 15 juillet"+             , "13 jusqu'au 15 juillet"+             , "13 juillet au 15 juillet"+             , "13 juillet - 15 juillet"+             , "entre le 13 et le 15 juillet"+             , "samedi 13 au dimanche 15 juillet"+             , "du samedi 13 au dimanche 15 juillet"+             , "du 13 au dimanche 15 juillet"+             ]+  , examples (datetimeInterval ((2013, 7, 1, 0, 0, 0), (2013, 7, 11, 0, 0, 0)) Day)+             [ "1er au 10 juillet"+             , "lundi 1er au mercredi 10 juillet"+             , "lundi 1 au mercredi 10 juillet"+             , "du lundi 1er au mercredi 10 juillet"+             , "du 1er au mercredi 10 juillet"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 19, 0, 0, 0)) Day)+             [ "du 13 au 18"+             , "entre le 13 et le 18"+             ]+  , examples (datetimeInterval ((2013, 6, 10, 0, 0, 0), (2013, 7, 2, 0, 0, 0)) Day)+             [ "10 juin au 1er juillet"+             , "entre le 10 juin et le 1er juillet"+             , "du 10 juin au 1er juillet"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 12, 0, 0)) Minute)+             [ "de 9h30 jusqu'à 11h jeudi"+             , "de 9 heures 30 à 11h jeudi"+             , "de 9 heures 30 a 11h jeudi"+             , "entre 9h30 et 11h jeudi"+             , "jeudi mais entre 9h30 et 11h"+             , "jeudi par exemple entre 9h30 et 11h"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "9h30 - 11h00 Jeudi"+             ]+  , examples (datetimeOpenInterval After (2013, 3, 8, 0, 0, 0) Day)+             [ "à partir du 8"+             , "à partir du 8 mars"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 14, 9, 30, 0) Minute)+             [ "à partir de 9h30 jeudi"+             , "jeudi après 9h30"+             , "jeudi matin à partir de 9 heures 30"+             ]+  , examples (datetimeOpenInterval After (2013, 11, 1, 16, 0, 0) Hour)+             [ "après 16h le 1er novembre"+             ]+  , examples (datetimeOpenInterval After (2013, 11, 1, 0, 0, 0) Day)+             [ "après le 1er novembre"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 16, 0, 0) Hour)+             [ "avant 16h"+             , "n'importe quand avant 16h"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 13, 17, 0, 0)) Hour)+             [ "demain jusqu'à 16h"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 20, 10, 0, 0) Hour)+             [ "le 20 à partir de 10h"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 15, 12, 0, 0) Hour)+             [ "vendredi à partir de midi"+             ]+  , examples (datetimeInterval ((2013, 2, 20, 0, 0, 0), (2013, 2, 20, 19, 0, 0)) Hour)+             [ "le 20 jusqu'à 18h"+             ]+  , examples (datetimeInterval ((2014, 9, 14, 0, 0, 0), (2014, 9, 21, 0, 0, 0)) Day)+             [ "14 - 20 sept. 2014"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "d'ici 2 semaines"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 27, 4, 0, 0)) Second)+             [ "dans les 15 jours"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "de 5 à 7"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "jeudi de 9h à 11h"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 15, 0, 0)) Hour)+             [ "entre midi et 2"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11h30-1h30"+             , "de 11h30 à 1h30"+             , "de 11h30 jusqu'à 1h30"+             ]+  , examples (datetime (2013, 9, 21, 13, 30, 0) Minute)+             [ "13h30 samedi 21 septembre"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "à seize heures CET"+             ]+  , examples (datetimeInterval ((2013, 3, 25, 0, 0, 0), (2013, 4, 1, 0, 0, 0)) Day)+             [ "fin mars"+             , "fin du mois de mars"+             ]+  , examples (datetimeInterval ((2013, 4, 1, 0, 0, 0), (2013, 4, 6, 0, 0, 0)) Day)+             [ "début avril"+             , "début du mois d'avril"+             ]+  , examples (datetimeInterval ((2013, 4, 1, 0, 0, 0), (2013, 4, 15, 0, 0, 0)) Day)+             [ "la première quinzaine d'avril"+             ]+  , examples (datetimeInterval ((2013, 4, 15, 0, 0, 0), (2013, 5, 1, 0, 0, 0)) Day)+             [ "la deuxième quinzaine d'avril"+             ]+  , examples (datetimeInterval ((2013, 4, 1, 0, 0, 0), (2013, 4, 6, 0, 0, 0)) Day)+             [ "début avril"+             , "début du mois d'avril"+             ]+  , examples (datetimeInterval ((2013, 12, 10, 0, 0, 0), (2013, 12, 20, 0, 0, 0)) Day)+             [ "mi-décembre"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "mars"+             , "en mars"+             , "au mois de mars"+             , "le mois de mars"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "jeudi 15"+             ]+  , examples (datetime (2013, 8, 15, 8, 0, 0) Hour)+             [ "jeudi 15 à 8h"+             ]+  ]
+ Duckling/Time/FR/Rules.hs view
@@ -0,0 +1,2179 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.FR.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleAujourdhui :: Rule+ruleAujourdhui = Rule+  { name = "aujourd'hui"+  , pattern =+    [ regex "(aujourd'? ?hui)|(ce jour)|(dans la journ(\x00e9|e)e?)|(en ce moment)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "lun\\.?(di)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleDayofmonthNamedmonth :: Rule+ruleDayofmonthNamedmonth = Rule+  { name = "<day-of-month> <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleHier :: Rule+ruleHier = Rule+  { name = "hier"+  , pattern =+    [ regex "hier|la veille"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleDbutDeJourne :: Rule+ruleDbutDeJourne = Rule+  { name = "début de journée"+  , pattern =+    [ regex "d(\x00e9|e)but de journ(\x00e9|e)e"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+        interval TTime.Open (hour False 6, hour False 10)+  }++ruleLeLendemainDuTime :: Rule+ruleLeLendemainDuTime = Rule+  { name = "le lendemain du <time>"+  , pattern =+    [ regex "(le|au)? ?lendemain du"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ cycleNthAfter True TG.Day 1 td+      _ -> Nothing+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "d(\x00e9|e)cembre|d(\x00e9|e)c\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleCePartofday :: Rule+ruleCePartofday = Rule+  { name = "ce <part-of-day>"+  , pattern =+    [ regex "cet?t?e?"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay . notLatent <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleCeTime :: Rule+ruleCeTime = Rule+  { name = "ce <time>"+  , pattern =+    [ regex "ce"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mar\\.?(di)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleDurationAvantTime :: Rule+ruleDurationAvantTime = Rule+  { name = "<duration> avant <time>"+  , pattern =+    [ dimension Duration+    , regex "avant"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++ruleMidi :: Rule+ruleMidi = Rule+  { name = "midi"+  , pattern =+    [ regex "midi"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sam\\.?(edi)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|au|jusqu'(au?|\x00e0)"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juillet|juil?\\."+    ]+  , prod = \_ -> tt $ month 7+  }++ruleDatetimeddMonthinterval :: Rule+ruleDatetimeddMonthinterval = Rule+  { name = "<datetime>-dd <month>(interval)"+  , pattern =+    [ dimension Time+    , regex "\\-|au|jusqu'au"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token RegexMatch (GroupMatch (match:_)):Token Time td2:_) -> do+        n <- parseInt match+        from <- intersect td2 td1+        to <- intersect (dayOfMonth n) td2+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleDeTimeofdayTimeofdayInterval :: Rule+ruleDeTimeofdayTimeofdayInterval = Rule+  { name = "de <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(midi )?de"+    , Predicate isATimeOfDay+    , regex "\\-|(jusqu')?(\x00e0|au?)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNProchainsCycle :: Rule+ruleNProchainsCycle = Rule+  { name = "n prochains <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "prochaine?s?|suivante?s?|apr(e|\x00e8|\x00e9)s"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain n+      _ -> Nothing+  }++ruleNDerniersCycle :: Rule+ruleNDerniersCycle = Rule+  { name = "n derniers <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "derni(e|\x00e8|\x00e9)re?s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleN True grain $ - n+      _ -> Nothing+  }++ruleAvantTimeofday :: Rule+ruleAvantTimeofday = Rule+  { name = "avant <time-of-day>"+  , pattern =+    [ regex "(n[ ']importe quand )?(avant|jusqu'(a|\x00e0))"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleEntreDatetimeEtDatetimeInterval :: Rule+ruleEntreDatetimeEtDatetimeInterval = Rule+  { name = "entre <datetime> et <datetime> (interval)"+  , pattern =+    [ regex "entre"+    , dimension Time+    , regex "et"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleDatetimedayofweekDdMonthinterval :: Rule+ruleDatetimedayofweekDdMonthinterval = Rule+  { name = "<datetime>-<day-of-week> dd <month>(interval)"+  , pattern =+    [ dimension Time+    , regex "\\-|(jusqu')?au"+    , Predicate isADayOfWeek+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:_:Token RegexMatch (GroupMatch (match:_)):Token Time td2:_) -> do+        n <- parseInt match+        from <- intersect td2 td1+        to <- intersect (dayOfMonth n) td2+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleHhhmmTimeofday :: Rule+ruleHhhmmTimeofday = Rule+  { name = "hh(:|h)mm (time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:h]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute (h < 12) h m+      _ -> Nothing+  }++ruleDdMm :: Rule+ruleDdMm = Rule+  { name = "dd mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9]) (1[0-2]|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleDdMmYyyy :: Rule+ruleDdMmYyyy = Rule+  { name = "dd mm yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9]) (1[0-2]|0?[1-9]) (\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "jeu\\.?(di)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleNamedmonthProchain :: Rule+ruleNamedmonthProchain = Rule+  { name = "<named-month> prochain"+  , pattern =+    [ dimension Time+    , regex "prochain"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleDiciDuration :: Rule+ruleDiciDuration = Rule+  { name = "d'ici <duration>"+  , pattern =+    [ regex "d'ici|dans l('|es?)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $+          interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+      _ -> Nothing+  }++ruleToussaint :: Rule+ruleToussaint = Rule+  { name = "toussaint"+  , pattern =+    [ regex "((la |la journ(\x00e9|e)e de la |jour de la )?toussaint|jour des morts)"+    ]+  , prod = \_ -> tt $ monthDay 11 1+  }++ruleDernierCycleDeTimeLatent :: Rule+ruleDernierCycleDeTimeLatent = Rule+  { name = "dernier <cycle> de <time> (latent)"+  , pattern =+    [ regex "derni(e|\x00e9|\x00e8)re?"+    , dimension TimeGrain+    , regex "d['e]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleDurationApresTime :: Rule+ruleDurationApresTime = Rule+  { name = "<duration> apres <time>"+  , pattern =+    [ dimension Duration+    , regex "apr(e|\x00e8)s"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleNCycleAprs :: Rule+ruleNCycleAprs = Rule+  { name = "n <cycle> après"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "(d')? ?apr(e|\x00e8|\x00e9)s|qui sui(t|ves?)|plus tard"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleNth grain n+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "(ce )?printemps"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 3 20, monthDay 6 21)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleNCycleAvant :: Rule+ruleNCycleAvant = Rule+  { name = "n <cycle> avant"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "(d')? ?avant|plus t(o|\x00f4)t"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleNth grain $ - n+      _ -> Nothing+  }++ruleDimTimeDuMatin :: Rule+ruleDimTimeDuMatin = Rule+  { name = "<dim time> du matin"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "((du|dans|de) )?((au|le|la) )?mat(in(\x00e9|e)?e?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let morning = partOfDay . mkLatent $+                        interval TTime.Open (hour False 0, hour False 12)+        in Token Time <$> intersect td morning+      _ -> Nothing+  }++ruleOrdinalWeekendDeTime :: Rule+ruleOrdinalWeekendDeTime = Rule+  { name = "<ordinal> week-end de <time>"+  , pattern =+    [ dimension Ordinal+    , regex "week(\\s|-)?end (d['eu]|en|du mois de)"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        from <- intersect (dayOfWeek 5) (hour False 18)+        to <- intersect (dayOfWeek 1) (hour False 0)+        td2 <- intersect td (interval TTime.Open (from, to))+        tt $ predNth (n - 1) False td2+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "janvier|janv\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleHourofdayEtQuart :: Rule+ruleHourofdayEtQuart = Rule+  { name = "<hour-of-day> et quart"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(et )?quart"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayEtDemi :: Rule+ruleHourofdayEtDemi = Rule+  { name = "<hour-of-day> et demi"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "et demie?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHourofdayEtTroisQuart :: Rule+ruleHourofdayEtTroisQuart = Rule+  { name = "<hour-of-day> et trois quarts"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(et )?(3|trois) quarts?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 45+      _ -> Nothing+  }++ruleHourofdayEtpassDeNumeral :: Rule+ruleHourofdayEtpassDeNumeral = Rule+  { name = "<hour-of-day> et|passé de <number>"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "et|(pass(\x00e9|e)e? de)"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayEtpassDeNumeralMinutes :: Rule+ruleHourofdayEtpassDeNumeralMinutes = Rule+  { name = "<hour-of-day> et|passé de <number> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "et|(pass(\x00e9|e)e? de)"+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(ute)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayInteger :: Rule+ruleHourofdayInteger = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayIntegerMinutes :: Rule+ruleHourofdayIntegerMinutes = Rule+  { name = "<hour-of-day> <integer> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(ute)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayMoinsIntegerAsRelativeMinutes :: Rule+ruleHourofdayMoinsIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> moins <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "moins( le)?"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayMoinsQuart :: Rule+ruleHourofdayMoinsQuart = Rule+  { name = "<hour-of-day> moins quart"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "moins( le)? quart"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> do+        t <- minutesBefore 15 td+        Just $ Token Time t+      _ -> Nothing+  }++ruleAprsLeDayofmonth :: Rule+ruleAprsLeDayofmonth = Rule+  { name = "après le <day-of-month>"+  , pattern =+    [ regex "(apr(e|\x00e8)s le|(a|\x00e0) partir du)"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . withDirection TTime.After $ dayOfMonth n+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mars|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleCycleDernier :: Rule+ruleCycleDernier = Rule+  { name = "<cycle> dernier"+  , pattern =+    [ dimension TimeGrain+    , regex "derni(\x00e8|e)re?|pass(\x00e9|e)e?|pr(e|\x00e9)c(e|\x00e9)dente?|(d')? ?avant"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleLeOrdinalCycleDeTime :: Rule+ruleLeOrdinalCycleDeTime = Rule+  { name = "le <ordinal> <cycle> de <time>"+  , pattern =+    [ regex "l[ea]"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "d['eu]|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleEnSemaine :: Rule+ruleEnSemaine = Rule+  { name = "en semaine"+  , pattern =+    [ regex "(pendant la |en )?semaine"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (dayOfWeek 1, dayOfWeek 5)+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/-mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[/-](1[0-2]|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleNamedmonthnameddayDernierpass :: Rule+ruleNamedmonthnameddayDernierpass = Rule+  { name = "<named-month|named-day> dernier|passé"+  , pattern =+    [ dimension Time+    , regex "derni(e|\x00e9|\x00e8)re?|pass(\x00e9|e)e?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "avril|avr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleLeCycleDernier :: Rule+ruleLeCycleDernier = Rule+  { name = "le <cycle> dernier"+  , pattern =+    [ regex "l[ae']? ?"+    , dimension TimeGrain+    , regex "derni(\x00e8|e)re?|pass(\x00e9|e)e?"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleNCyclePassesprecedents :: Rule+ruleNCyclePassesprecedents = Rule+  { name = "n <cycle> passes|precedents"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "pass(e|\x00e8|\x00e9)(e|\x00e8|\x00e9)?s?|pr(e|\x00e9)c(e|\x00e9)dente?s?|(d')? ?avant|plus t(o|\x00f4)t"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleN True grain $ - n+      _ -> Nothing+  }++ruleSoir :: Rule+ruleSoir = Rule+  { name = "soir"+  , pattern =+    [ regex "soir(\x00e9|e)?e?"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 18, hour False 0)+  }++ruleDbutDeSoire :: Rule+ruleDbutDeSoire = Rule+  { name = "début de soirée"+  , pattern =+    [ regex "d(\x00e9|e)but de soir(\x00e9|e)e?"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 18, hour False 21)+  }++ruleFinDeSoire :: Rule+ruleFinDeSoire = Rule+  { name = "fin de soirée"+  , pattern =+    [ regex "fin de soir(\x00e9|e)e?"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 21, hour False 0)+  }++ruleDbutDeMatine :: Rule+ruleDbutDeMatine = Rule+  { name = "début de matinée"+  , pattern =+    [ regex "le matin (tr(e|\x00e8)s )?t(\x00f4|o)t|(tr(e|\x00e8)s )?t(\x00f4|o)t le matin|d(\x00e9|e)but de matin(\x00e9|e)e"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 7, hour False 9)+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "ven\\.?(dredi)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDdddMonthinterval :: Rule+ruleDdddMonthinterval = Rule+  { name = "dd-dd <month>(interval)"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|au|jusqu'au"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):_:Token RegexMatch (GroupMatch (m2:_)):Token Time td:_) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        from <- intersect td (dayOfMonth d1)+        to <- intersect td (dayOfMonth d2)+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour (n < 12) n+      _ -> Nothing+  }++ruleDuDddayofweekDdMonthinterval :: Rule+ruleDuDddayofweekDdMonthinterval = Rule+  { name = "du dd-<day-of-week> dd <month>(interval)"+  , pattern =+    [ regex "du"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|au|jusqu'au"+    , Predicate isADayOfWeek+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (m1:_)):_:_:Token RegexMatch (GroupMatch (m2:_)):Token Time td:_) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        from <- intersect (dayOfMonth d1) td+        to <- intersect (dayOfMonth d2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleDbutNamedmonthinterval :: Rule+ruleDbutNamedmonthinterval = Rule+  { name = "début <named-month>(interval)"+  , pattern =+    [ regex "d(\x00e9|e)but( du mois d[e'] ?)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfMonth 1) td+        to <- intersect (dayOfMonth 5) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "f(\x00e9|e)vrier|f(\x00e9|e)v\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleMilieuDeJourne :: Rule+ruleMilieuDeJourne = Rule+  { name = "milieu de journée"+  , pattern =+    [ regex "milieu de journ(\x00e9|e)e"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 11, hour False 16)+  }++ruleFinDeJourne :: Rule+ruleFinDeJourne = Rule+  { name = "fin de journée"+  , pattern =+    [ regex "fin de journ(\x00e9|e)e"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 17, hour False 21)+  }++ruleLeCycleDeTime :: Rule+ruleLeCycleDeTime = Rule+  { name = "le <cycle> de <time>"+  , pattern =+    [ regex "l[ea]"+    , dimension TimeGrain+    , regex "d['eu]|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "(cet )?hiver"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 12 21, monthDay 3 20)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "(cet )?(\x00e9|e)t(\x00e9|e)"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 6 21, monthDay 9 23)+  }++ruleAprsmidi :: Rule+ruleAprsmidi = Rule+  { name = "après-midi"+  , pattern =+    [ regex "apr(e|\x00e9|\x00e8)s?[ \\-]?midi"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 12, hour False 19)+  }++ruleNoel :: Rule+ruleNoel = Rule+  { name = "noel"+  , pattern =+    [ regex "(jour de )?no(e|\x00eb)l"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleDayofweekProchain :: Rule+ruleDayofweekProchain = Rule+  { name = "<day-of-week> prochain"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "prochain"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleDemain :: Rule+ruleDemain = Rule+  { name = "demain"+  , pattern =+    [ regex "(demain)|(le lendemain)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleNamedmonthnameddaySuivantdaprs :: Rule+ruleNamedmonthnameddaySuivantdaprs = Rule+  { name = "<named-month|named-day> suivant|d'après"+  , pattern =+    [ dimension Time+    , regex "suivante?s?|d'apr(e|\x00e9|\x00e8)s"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleNameddayEnHuit :: Rule+ruleNameddayEnHuit = Rule+  { name = "<named-day> en huit"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "en (huit|8)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleHhmmMilitaryTimeofday :: Rule+ruleHhmmMilitaryTimeofday = Rule+  { name = "hhmm (military time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt . mkLatent $ hourMinute False h m+      _ -> Nothing+  }++ruleDimTimeDuSoir :: Rule+ruleDimTimeDuSoir = Rule+  { name = "<dim time> du soir"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "((du|dans|de) )?((au|le|la) )?soir(\x00e9|e)?e?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let td2 = mkLatent . partOfDay $+                    interval TTime.Open (hour False 16, hour False 0)+        in Token Time <$> intersect td td2+      _ -> Nothing+  }++ruleAprsTimeofday :: Rule+ruleAprsTimeofday = Rule+  { name = "après <time-of-day>"+  , pattern =+    [ regex "(apr(e|\x00e8)s|(a|\x00e0) partir de)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleAprsLeDjeuner :: Rule+ruleAprsLeDjeuner = Rule+  { name = "après le déjeuner"+  , pattern =+    [ regex "apr(e|\x00e8)s (le )?d(e|\x00e9|\x00e8)jeuner"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 13, hour False 17)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleErMai :: Rule+ruleErMai = Rule+  { name = "1er mai"+  , pattern =+    [ regex "f(e|\x00ea)te du travail"+    ]+  , prod = \_ -> tt $ monthDay 5 1+  }++rulePremireQuinzaineDeNamedmonthinterval :: Rule+rulePremireQuinzaineDeNamedmonthinterval = Rule+  { name = "première quinzaine de <named-month>(interval)"+  , pattern =+    [ regex "(premi(\x00e8|e)re|1 ?(\x00e8|e)re) (quinzaine|15 ?aine) d[e']"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfMonth 1) td+        to <- intersect (dayOfMonth 14) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleDeDatetimeDatetimeInterval :: Rule+ruleDeDatetimeDatetimeInterval = Rule+  { name = "de <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "de|depuis|du"+    , dimension Time+    , regex "\\-|au|jusqu'(au?|\x00e0)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleAvanthier :: Rule+ruleAvanthier = Rule+  { name = "avant-hier"+  , pattern =+    [ regex "avant[- ]?hier"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleCycleProchainsuivantdaprs :: Rule+ruleCycleProchainsuivantdaprs = Rule+  { name = "<cycle> prochain|suivant|d'après"+  , pattern =+    [ dimension TimeGrain+    , regex "prochaine?|suivante?|qui suit|(d')? ?apr(e|\x00e8|\x00e9)s"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juin|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleAprsLeTravail :: Rule+ruleAprsLeTravail = Rule+  { name = "après le travail"+  , pattern =+    [ regex "apr(e|\x00e8)s (le )?travail"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 17, hour False 21)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "ao(\x00fb|u)t|aou\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleLeDayofmonthDatetime :: Rule+ruleLeDayofmonthDatetime = Rule+  { name = "le <day-of-month> à <datetime>"+  , pattern =+    [ regex "le"+    , Predicate isDOMInteger+    , regex "(a|\x00e0)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token Time td:_) -> do+        n <- getIntValue token+        Token Time <$> intersect (dayOfMonth n) td+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "week(\\s|-)?end"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleCedansLeCycle :: Rule+ruleCedansLeCycle = Rule+  { name = "ce|dans le <cycle>"+  , pattern =+    [ regex "(cet?t?e?s?)|(dans l[ae']? ?)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleDansDuration :: Rule+ruleDansDuration = Rule+  { name = "dans <duration>"+  , pattern =+    [ regex "dans"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleOrdinalCycleDeTime :: Rule+ruleOrdinalCycleDeTime = Rule+  { name = "<ordinal> <cycle> de <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "d['eu]|en"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleAvantLeDjeuner :: Rule+ruleAvantLeDjeuner = Rule+  { name = "avant le déjeuner"+  , pattern =+    [ regex "avant (le )?d(e|\x00e9|\x00e8)jeuner"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 10, hour False 12)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleDernierWeekendDeTime :: Rule+ruleDernierWeekendDeTime = Rule+  { name = "dernier week-end de <time>"+  , pattern =+    [ regex "dernier week(\\s|-)?end (d['eu]|en|du mois de)"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfWeek 5) (hour False 18)+        to <- intersect (dayOfWeek 1) (hour False 0)+        tt $ predLastOf (interval TTime.Open (from, to)) td+      _ -> Nothing+  }++ruleLeCycleProchainsuivantdaprs :: Rule+ruleLeCycleProchainsuivantdaprs = Rule+  { name = "le <cycle> prochain|suivant|d'après"+  , pattern =+    [ regex "l[ae']? ?|une? ?"+    , dimension TimeGrain+    , regex "prochaine?|suivante?|qui suit|(d'? ?)?apr(e|\x00e8|\x00e9)s"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleDimTimePartofday :: Rule+ruleDimTimePartofday = Rule+  { name = "<dim time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleEnNamedmonth :: Rule+ruleEnNamedmonth = Rule+  { name = "en <named-month>"+  , pattern =+    [ regex "en|au mois de?'?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleEntreTimeofdayEtTimeofdayInterval :: Rule+ruleEntreTimeofdayEtTimeofdayInterval = Rule+  { name = "entre <time-of-day> et <time-of-day> (interval)"+  , pattern =+    [ regex "entre"+    , Predicate isATimeOfDay+    , regex "et"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleIntersectByDeOr :: Rule+ruleIntersectByDeOr = Rule+  { name = "intersect by 'de' or ','"+  , pattern =+    [ Predicate isNotLatent+    , regex "de|,"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleDeuximeQuinzaineDeNamedmonthinterval :: Rule+ruleDeuximeQuinzaineDeNamedmonthinterval = Rule+  { name = "deuxième quinzaine de <named-month>(interval)"+  , pattern =+    [ regex "(deuxi(\x00e8|e)me|2 ?(\x00e8|e)me) (quinzaine|15 ?aine) d[e']"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfMonth 15) td+        let to = cycleLastOf TG.Day td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++rulePartofdayDuDimTime :: Rule+rulePartofdayDuDimTime = Rule+  { name = "<part-of-day> du <dim time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "du"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(1[0-2]|0?[1-9])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleMilieuDeSemaine :: Rule+ruleMilieuDeSemaine = Rule+  { name = "milieu de semaine"+  , pattern =+    [ regex "(en |au )?milieu de (cette |la )?semaine"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (dayOfWeek 3, dayOfWeek 4)+  }++ruleDbutDeSemaine :: Rule+ruleDbutDeSemaine = Rule+  { name = "début de semaine"+  , pattern =+    [ regex "(en |au )?d(\x00e9|e)but de (cette |la )?semaine"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (dayOfWeek 1, dayOfWeek 2)+  }++ruleTimeofdayHeures :: Rule+ruleTimeofdayHeures = Rule+  { name = "<time-of-day> heures"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "h\\.?(eure)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleDernierDayofweekDeTimeLatent :: Rule+ruleDernierDayofweekDeTimeLatent = Rule+  { name = "dernier <day-of-week> de <time> (latent)"+  , pattern =+    [ regex "derni(e|\x00e9|\x00e8)re?"+    , Predicate isADayOfWeek+    , regex "d['e]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleCeDayofweek :: Rule+ruleCeDayofweek = Rule+  { name = "ce <day-of-week>"+  , pattern =+    [ regex "ce"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleDuDatetimedayofweekDdMonthinterval :: Rule+ruleDuDatetimedayofweekDdMonthinterval = Rule+  { name = "du <datetime>-<day-of-week> dd <month>(interval)"+  , pattern =+    [ regex "du"+    , dimension Time+    , regex "\\-|au|jusqu'au"+    , Predicate isADayOfWeek+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:_:Token RegexMatch (GroupMatch (m:_)):Token Time td2:_) -> do+        n <- parseInt m+        from <- intersect td2 td1+        to <- intersect (dayOfMonth n) td2+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleDuDdAuDdinterval :: Rule+ruleDuDdAuDdinterval = Rule+  { name = "du dd au dd(interval)"+  , pattern =+    [ regex "du"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "au|jusqu'au"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (m1:_)):_:Token RegexMatch (GroupMatch (m2:_)):_) -> do+        n1 <- parseInt m1+        n2 <- parseInt m2+        tt $ interval TTime.Closed (dayOfMonth n1, dayOfMonth n2)+      _ -> Nothing+  }++ruleMatin :: Rule+ruleMatin = Rule+  { name = "matin"+  , pattern =+    [ regex "mat(in(\x00e9|e)?e?)?"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 4, hour False 12)+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "(cet )?automne"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 9 23, monthDay 12 21)+  }++ruleVersTimeofday :: Rule+ruleVersTimeofday = Rule+  { name = "à|vers <time-of-day>"+  , pattern =+    [ regex "(vers|autour de|(a|\x00e0) environ|aux alentours de|(a|\x00e0))"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleFinNamedmonthinterval :: Rule+ruleFinNamedmonthinterval = Rule+  { name = "fin <named-month>(interval)"+  , pattern =+    [ regex "fin( du mois d[e']? ?)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfMonth 25) td+        let to = cycleLastOf TG.Day td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleDayofweekDayofmonth :: Rule+ruleDayofweekDayofmonth = Rule+  { name = "<day-of-week> <day-of-month>"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNameddayEnQuinze :: Rule+ruleNameddayEnQuinze = Rule+  { name = "<named-day> en quinze"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "en (quinze|15)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 2 False td+      _ -> Nothing+  }++ruleLeDayofmonthNonOrdinal :: Rule+ruleLeDayofmonthNonOrdinal = Rule+  { name = "le <day-of-month> (non ordinal)"+  , pattern =+    [ regex "le"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt $ dayOfMonth n+      _ -> Nothing+  }++ruleIntersectByMaisparExempleplutt :: Rule+ruleIntersectByMaisparExempleplutt = Rule+  { name = "intersect by 'mais/par exemple/plutôt'"+  , pattern =+    [ Predicate isNotLatent+    , regex "mais|par exemple|plut(\x00f4|o)t"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleLeCycleAprssuivantTime :: Rule+ruleLeCycleAprssuivantTime = Rule+  { name = "le <cycle> après|suivant <time>"+  , pattern =+    [ regex "l[ea']? ?"+    , dimension TimeGrain+    , regex "suivante?|apr(e|\x00e8|\x00e9)s"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleEntreDdEtDdMonthinterval :: Rule+ruleEntreDdEtDdMonthinterval = Rule+  { name = "entre dd et dd <month>(interval)"+  , pattern =+    [ regex "entre( le)?"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "et( le)?"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (m1:_)):_:Token RegexMatch (GroupMatch (m2:_)):Token Time td:_) -> do+        n1 <- parseInt m1+        n2 <- parseInt m2+        from <- intersect (dayOfMonth n1) td+        to <- intersect (dayOfMonth n2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleAprsdemain :: Rule+ruleAprsdemain = Rule+  { name = "après-demain"+  , pattern =+    [ regex "apr(e|\x00e8)s[- ]?demain"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mai"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "dim\\.?(anche)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleFinDeSemaine :: Rule+ruleFinDeSemaine = Rule+  { name = "fin de semaine"+  , pattern =+    [ regex "(en |(\x00e0|a) la )?fin de (cette |la )?semaine"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (dayOfWeek 4, dayOfWeek 7)+  }++ruleIlYADuration :: Rule+ruleIlYADuration = Rule+  { name = "il y a <duration>"+  , pattern =+    [ regex "il y a"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleDudansLePartofday :: Rule+ruleDudansLePartofday = Rule+  { name = "du|dans le <part-of-day>"+  , pattern =+    [ regex "du|dans l[ae']? ?|au|en|l[ae' ]|d(\x00e8|e)s l?[ae']? ?"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleAuDjeuner :: Rule+ruleAuDjeuner = Rule+  { name = "au déjeuner"+  , pattern =+    [ regex "((\x00e0|a) l(')?heure du|pendant( le)?|au)? d(e|\x00e9|\x00e8)jeuner"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 12, hour False 14)+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "octobre|oct\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleMaintenant :: Rule+ruleMaintenant = Rule+  { name = "maintenant"+  , pattern =+    [ regex "maintenant|(tout de suite)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleMilieuDeMatine :: Rule+ruleMilieuDeMatine = Rule+  { name = "milieu de matinée"+  , pattern =+    [ regex "milieu de matin(\x00e9|e)e"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 9, hour False 11)+  }++ruleFinDeMatine :: Rule+ruleFinDeMatine = Rule+  { name = "fin de matinée"+  , pattern =+    [ regex "fin de matin(\x00e9|e)e"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 10, hour False 12)+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/-mm/-yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[/-](1[0-2]|0?[1-9])[-/](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleLeCycleAvantprcdentTime :: Rule+ruleLeCycleAvantprcdentTime = Rule+  { name = "le <cycle> avant|précédent <time>"+  , pattern =+    [ regex "l[ea']? ?"+    , dimension TimeGrain+    , regex "avant|pr(\x00e9|e)c(\x00e9|e)dent"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleDayOfMonthPremier :: Rule+ruleDayOfMonthPremier = Rule+  { name = "day of month (premier)"+  , pattern =+    [ regex "premier|prem\\.?|1er|1 er"+    ]+  , prod = \_ -> tt $ dayOfMonth 1+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\\-|(jusqu')?(au?|\x00e0)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleLeVeilleDuTime :: Rule+ruleLeVeilleDuTime = Rule+  { name = "le veille du <time>"+  , pattern =+    [ regex "(la )?veille du"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ cycleNthAfter True TG.Day (-1) td+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "novembre|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDbutDaprsmidi :: Rule+ruleDbutDaprsmidi = Rule+  { name = "début d'après-midi"+  , pattern =+    [ regex "d(\x00e9|e)but d'apr(e|\x00e9|\x00e8)s?[ \\-]?midi"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 12, hour False 14)+  }++ruleLeTime :: Rule+ruleLeTime = Rule+  { name = "le <time>"+  , pattern =+    [ regex "l[ea]"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleSoirDeNol :: Rule+ruleSoirDeNol = Rule+  { name = "soir de noël"+  , pattern =+    [ regex "soir(\x00e9e)? de no(e|\x00eb)l"+    ]+  , prod = \_ -> do+      from <- intersect (monthDay 12 24) (hour False 18)+      to <- intersect (monthDay 12 25) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleDayofweekDayofmonthTimeofday :: Rule+ruleDayofweekDayofmonthTimeofday = Rule+  { name = "<day-of-week> <day-of-month> à <time-of-day>)"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMInteger+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:token:Token Time td2:_) -> do+        dom <- intersectDOM td1 token+        Token Time <$> intersect dom td2+      _ -> Nothing+  }++ruleMilieuDaprsmidi :: Rule+ruleMilieuDaprsmidi = Rule+  { name = "fin d'après-midi"+  , pattern =+    [ regex "milieu d'apr(e|\x00e9|\x00e8)s?[ \\-]?midi"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 15, hour False 17)+  }++ruleFinDaprsmidi :: Rule+ruleFinDaprsmidi = Rule+  { name = "fin d'après-midi"+  , pattern =+    [ regex "fin d'apr(e|\x00e9|\x00e8)s?[ \\-]?midi"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 17, hour False 19)+  }++ruleJourDeLan :: Rule+ruleJourDeLan = Rule+  { name = "jour de l'an"+  , pattern =+    [ regex "(jour de l'|nouvel )an"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mer\\.?(credi)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleMinuit :: Rule+ruleMinuit = Rule+  { name = "minuit"+  , pattern =+    [ regex "minuit"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleNCycleSuivants :: Rule+ruleNCycleSuivants = Rule+  { name = "n <cycle> suivants"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "prochaine?s?|suivante?s?|apr(e|\x00e8|\x00e9)s|qui sui(t|ves?)|plus tard"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain n+      _ -> Nothing+  }++ruleNamedmonth13 :: Rule+ruleNamedmonth13 = Rule+  { name = "<named-month>"+  , pattern =+    [ regex "mi[- ]"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from <- intersect (dayOfMonth 10) td+        to <- intersect (dayOfMonth 19) td+        tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleDayofweekErdayofweekDdMonthinterval :: Rule+ruleDayofweekErdayofweekDdMonthinterval = Rule+  { name = "<day-of-week> 1er-<day-of-week> dd <month>(interval)"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "premier|prem\\.?|1er|1 er"+    , regex "\\-|au|jusqu'au"+    , Predicate isADayOfWeek+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:_:_:_:Token RegexMatch (GroupMatch (m:_)):Token Time td:_) -> do+        n <- parseInt m+        from <- intersect (dayOfMonth 1) td+        to <- intersect (dayOfMonth n) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "septembre|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleFinDuMois :: Rule+ruleFinDuMois = Rule+  { name = "fin du mois"+  , pattern =+    [ regex "(((a|\x00e0) )?la )?fin (du|de) mois"+    ]+  , prod = \_ -> do+      let from = cycleNthAfter False TG.Day (- 10) $ cycleNth TG.Month 1+          to = cycleNth TG.Month 1+      tt . mkLatent . partOfDay $ interval TTime.Open (from, to)+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAprsLeDayofmonth+  , ruleAprsLeDjeuner+  , ruleAprsLeTravail+  , ruleAprsTimeofday+  , ruleAprsdemain+  , ruleAprsmidi+  , ruleAuDjeuner+  , ruleAujourdhui+  , ruleAvantLeDjeuner+  , ruleAvantTimeofday+  , ruleAvanthier+  , ruleCeDayofweek+  , ruleCePartofday+  , ruleCeTime+  , ruleCedansLeCycle+  , ruleCycleDernier+  , ruleCycleProchainsuivantdaprs+  , ruleDansDuration+  , ruleDatetimeDatetimeInterval+  , ruleDatetimedayofweekDdMonthinterval+  , ruleDatetimeddMonthinterval+  , ruleDayOfMonthPremier+  , ruleDayofmonthNamedmonth+  , ruleDayofweekDayofmonth+  , ruleDayofweekDayofmonthTimeofday+  , ruleDayofweekErdayofweekDdMonthinterval+  , ruleDayofweekProchain+  , ruleDbutDaprsmidi+  , ruleDbutDeJourne+  , ruleDbutDeMatine+  , ruleDbutDeSemaine+  , ruleDbutNamedmonthinterval+  , ruleDdMm+  , ruleDdMmYyyy+  , ruleDdddMonthinterval+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDeDatetimeDatetimeInterval+  , ruleDeTimeofdayTimeofdayInterval+  , ruleDemain+  , ruleDernierCycleDeTimeLatent+  , ruleDernierDayofweekDeTimeLatent+  , ruleDernierWeekendDeTime+  , ruleDeuximeQuinzaineDeNamedmonthinterval+  , ruleDiciDuration+  , ruleDimTimeDuMatin+  , ruleDimTimeDuSoir+  , ruleDimTimePartofday+  , ruleDuDatetimedayofweekDdMonthinterval+  , ruleDuDdAuDdinterval+  , ruleDuDddayofweekDdMonthinterval+  , ruleDudansLePartofday+  , ruleDurationApresTime+  , ruleDurationAvantTime+  , ruleEnNamedmonth+  , ruleEnSemaine+  , ruleEntreDatetimeEtDatetimeInterval+  , ruleEntreDdEtDdMonthinterval+  , ruleEntreTimeofdayEtTimeofdayInterval+  , ruleErMai+  , ruleMilieuDaprsmidi+  , ruleFinDaprsmidi+  , ruleMilieuDeJourne+  , ruleFinDeJourne+  , ruleMilieuDeMatine+  , ruleFinDeMatine+  , ruleFinDeSemaine+  , ruleFinNamedmonthinterval+  , ruleHhhmmTimeofday+  , ruleHhmmMilitaryTimeofday+  , ruleHier+  , ruleIlYADuration+  , ruleIntersect+  , ruleIntersectByDeOr+  , ruleIntersectByMaisparExempleplutt+  , ruleJourDeLan+  , ruleLeCycleAprssuivantTime+  , ruleLeCycleAvantprcdentTime+  , ruleLeCycleDeTime+  , ruleLeCycleDernier+  , ruleLeCycleProchainsuivantdaprs+  , ruleLeDayofmonthDatetime+  , ruleLeDayofmonthNonOrdinal+  , ruleLeLendemainDuTime+  , ruleLeOrdinalCycleDeTime+  , ruleLeTime+  , ruleLeVeilleDuTime+  , ruleMaintenant+  , ruleMatin+  , ruleMidi+  , ruleMilieuDeSemaine+  , ruleMinuit+  , ruleNCycleAprs+  , ruleNCycleAvant+  , ruleNCyclePassesprecedents+  , ruleNCycleSuivants+  , ruleNDerniersCycle+  , ruleNProchainsCycle+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNameddayEnHuit+  , ruleNameddayEnQuinze+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth13+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthProchain+  , ruleNamedmonthnameddayDernierpass+  , ruleNamedmonthnameddaySuivantdaprs+  , ruleNoel+  , ruleOrdinalCycleDeTime+  , ruleOrdinalWeekendDeTime+  , rulePartofdayDuDimTime+  , rulePremireQuinzaineDeNamedmonthinterval+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleSoir+  , ruleDbutDeSoire+  , ruleFinDeSoire+  , ruleSoirDeNol+  , ruleTimeofdayHeures+  , ruleTimeofdayLatent+  , ruleTimeofdayTimeofdayInterval+  , ruleToussaint+  , ruleVersTimeofday+  , ruleWeekend+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYyyymmdd+  , ruleHourofdayMoinsQuart+  , ruleHourofdayMoinsIntegerAsRelativeMinutes+  , ruleHourofdayIntegerMinutes+  , ruleHourofdayInteger+  , ruleHourofdayEtpassDeNumeral+  , ruleHourofdayEtpassDeNumeralMinutes+  , ruleHourofdayEtTroisQuart+  , ruleHourofdayEtQuart+  , ruleHourofdayEtDemi+  , ruleFinDuMois+  , ruleTimezone+  ]
+ Duckling/Time/GA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.GA.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "anois"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "inniu"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "inné"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "arú inné"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "amárach"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "arú amárach"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "dé luain"+             , "an luan"+             , "an luan seo"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "an luan seo chugainn"+             , "an luan seo atá ag teacht"+             , "dé luain seo chugainn"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "18/2/2013"+             ]+  ]
+ Duckling/Time/GA/Rules.hs view
@@ -0,0 +1,872 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.GA.Rules+  ( rules ) where++import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleArInn :: Rule+ruleArInn = Rule+  { name = "arú inné"+  , pattern =+    [ regex "ar(\x00fa|u) inn(\x00e9|e)"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "luai?n|lu\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleNollaigNaMban :: Rule+ruleNollaigNaMban = Rule+  { name = "Nollaig na mBan"+  , pattern =+    [ regex "(l(\x00e1|a) |an )?nollaig (bheag|na mban)"+    ]+  , prod = \_ -> tt $ monthDay 1 6+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(na )?nollai?g|nol\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mh?(\x00e1|a)irt|m(\x00e1|a)?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sathai?rn|sa\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?i(\x00fa|u)il|i(\x00fa|u)i\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleInniu :: Rule+ruleInniu = Rule+  { name = "inniu"+  , pattern =+    [ regex "inniu"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleAnOrdinalCycleINdiaidhTime :: Rule+ruleAnOrdinalCycleINdiaidhTime = Rule+  { name = "an <ordinal> <cycle> i ndiaidh <time>"+  , pattern =+    [ regex "an"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "(i ndiaidh|tar (\x00e9|e)is)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleInn :: Rule+ruleInn = Rule+  { name = "inné"+  , pattern =+    [ regex "inn(\x00e9|e)"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleLFhileBrde :: Rule+ruleLFhileBrde = Rule+  { name = "Lá Fhéile Bríde"+  , pattern =+    [ regex "(l(\x00e1|a) )?(fh(e|\x00e9)ile|'?le) bh?r(\x00ed|i)de"+    ]+  , prod = \_ -> tt $ monthDay 2 1+  }++ruleLFhileVailintn :: Rule+ruleLFhileVailintn = Rule+  { name = "Lá Fhéile Vailintín"+  , pattern =+    [ regex "(l(\x00e1|a) )?(fh(e|\x00e9)ile|'?le) vailint(\x00ed|i)n"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleTimeSeo :: Rule+ruleTimeSeo = Rule+  { name = "<time> seo"+  , pattern =+    [ dimension Time+    , regex "seo"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleTimeSeoChaite :: Rule+ruleTimeSeoChaite = Rule+  { name = "<time> seo chaite"+  , pattern =+    [ dimension Time+    , regex "seo ch?aite"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleTimeSeoChugainn :: Rule+ruleTimeSeoChugainn = Rule+  { name = "<time> seo chugainn"+  , pattern =+    [ Predicate isNotLatent+    , regex "seo (chugainn|at(a|\x00e1) ag teacht)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "d(\x00e9|e)ardaoin|d(\x00e9|e)?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleAmrach :: Rule+ruleAmrach = Rule+  { name = "amárach"+  , pattern =+    [ regex "am(\x00e1|a)rach"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(an )?t?ean(\x00e1|a)ir|ean\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(an )?mh?(\x00e1|a)rta|m(\x00e1|a)r\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleOrdinalRithe :: Rule+ruleOrdinalRithe = Rule+  { name = "<ordinal> ráithe"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleAnnaCycleRoimhTime :: Rule+ruleAnnaCycleRoimhTime = Rule+  { name = "(an|na) <cycle> roimh <time>"+  , pattern =+    [ regex "the"+    , dimension TimeGrain+    , regex "roimh"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleCycleShin :: Rule+ruleCycleShin = Rule+  { name = "<cycle> ó shin"+  , pattern =+    [ dimension TimeGrain+    , regex "(\x00f3|o) shin"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt . cycleNth grain $ 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])/(0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        m <- parseInt m2+        d <- parseInt m1+        tt $ monthDay m d+      _ -> Nothing+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(an )?t?aibre(\x00e1|a)i?n|abr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleIGceannCycle :: Rule+ruleIGceannCycle = Rule+  { name = "i gceann <cycle>"+  , pattern =+    [ regex "(i|faoi) g?ch?eann"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_) ->+        tt $ cycleN True grain (TOrdinal.value od)+      _ -> Nothing+  }++ruleAnCycleDeTime :: Rule+ruleAnCycleDeTime = Rule+  { name = "an <cycle> de <time>"+  , pattern =+    [ regex "an"+    , dimension TimeGrain+    , regex "d[e']"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "h?aoine|ao\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleOrdinalRitheYear :: Rule+ruleOrdinalRitheYear = Rule+  { name = "<ordinal> ráithe <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleCycleInniu :: Rule+ruleCycleInniu = Rule+  { name = "<cycle> ó inniu"+  , pattern =+    [ Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    , regex "(\x00f3|o)(n l(\x00e1|a) (at(\x00e1|a) )?)?inniu"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(na )?feabhra|fea\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleOrdinalCycleINdiaidhTime :: Rule+ruleOrdinalCycleINdiaidhTime = Rule+  { name = "<ordinal> <cycle> i ndiaidh <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "(i ndiaidh|tar (\x00e9|e)is)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleAnDayofmonthOrdinal :: Rule+ruleAnDayofmonthOrdinal = Rule+  { name = "an <day-of-month> (ordinal)"+  , pattern =+    [ regex "an|na"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt $ dayOfMonth n+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(an )?mh?eith(ea|i)mh|mei\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(na )?l(\x00fa|u)nasa|l(\x00fa|u)n\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleAnOrdinalCycleDeTime :: Rule+ruleAnOrdinalCycleDeTime = Rule+  { name = "an <ordinal> <cycle> de <time>"+  , pattern =+    [ regex "an"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "d[e']"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleLNaNaithreacha :: Rule+ruleLNaNaithreacha = Rule+  { name = "Lá na nAithreacha"+  , pattern =+    [ regex "l(\x00e1|a) na naithreacha"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 2 7 6+  }++ruleArAmrach :: Rule+ruleArAmrach = Rule+  { name = "arú amárach"+  , pattern =+    [ regex "ar(\x00fa|u) am(\x00e1|a)rach"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleOrdinalCycleDeTime :: Rule+ruleOrdinalCycleDeTime = Rule+  { name = "<ordinal> <cycle> de <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "d[e']"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleArDate :: Rule+ruleArDate = Rule+  { name = "ar <date>"+  , pattern =+    [ regex "ar"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleAnNollaig :: Rule+ruleAnNollaig = Rule+  { name = "An Nollaig"+  , pattern =+    [ regex "(l(\x00e1|a) |an )?(nollai?g)"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "ar an"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleAnois :: Rule+ruleAnois = Rule+  { name = "anois"+  , pattern =+    [ regex "anois|(ag an (t-?)?am seo)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLFhilePdraig :: Rule+ruleLFhilePdraig = Rule+  { name = "Lá Fhéile Pádraig"+  , pattern =+    [ regex "(l(\x00e1|a) )?(fh(e|\x00e9)ile|'?le) ph?(\x00e1|a)draig"+    ]+  , prod = \_ -> tt $ monthDay 3 17+  }++ruleAnCycleINdiaidhTime :: Rule+ruleAnCycleINdiaidhTime = Rule+  { name = "an <cycle> i ndiaidh <time>"+  , pattern =+    [ regex "the"+    , dimension TimeGrain+    , regex "(i ndiaidh|tar (\x00e9|e)is)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ dayOfMonth n+      _ -> Nothing+  }++ruleAnCycleSeo :: Rule+ruleAnCycleSeo = Rule+  { name = "an <cycle> seo"+  , pattern =+    [ regex "an"+    , dimension TimeGrain+    , regex "seo"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(na )?bh?ealtaine|bea\\.?"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "domhnai?[cg]h|do\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleAnDayofmonthNonOrdinal :: Rule+ruleAnDayofmonthNonOrdinal = Rule+  { name = "an <day-of-month> (non ordinal)"+  , pattern =+    [ regex "an|na"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleDNamedday :: Rule+ruleDNamedday = Rule+  { name = "dé named-day"+  , pattern =+    [ regex "d(\x00e9|e)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?dh?eireadh f(\x00f3|o)mhair|def?\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleCycleRoimhTime :: Rule+ruleCycleRoimhTime = Rule+  { name = "<cycle> roimh <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "roimhe?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[-/](0?[1-9]|1[0-2])[/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?(na )?samh(ain|na)|sam\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleAnNamedday :: Rule+ruleAnNamedday = Rule+  { name = "an named-day"+  , pattern =+    [ regex "an"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "ch?(\x00e9|e)adaoin|c(\x00e9|e)\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleCycleINdiaidhTime :: Rule+ruleCycleINdiaidhTime = Rule+  { name = "<cycle> i ndiaidh <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(i ndiaidh|tar (\x00e9|e)is)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(mh?(\x00ed|i) )?mh?e(\x00e1|a)n f(\x00f3|o)mhair|mef?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:Token RegexMatch (GroupMatch (match:_)):_) -> do+        intVal <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year intVal)+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAbsorptionOfAfterNamedDay+  , ruleAmrach+  , ruleAnCycleDeTime+  , ruleAnCycleINdiaidhTime+  , ruleAnCycleSeo+  , ruleAnDayofmonthNonOrdinal+  , ruleAnDayofmonthOrdinal+  , ruleAnNamedday+  , ruleAnNollaig+  , ruleAnOrdinalCycleDeTime+  , ruleAnOrdinalCycleINdiaidhTime+  , ruleAnnaCycleRoimhTime+  , ruleAnois+  , ruleArAmrach+  , ruleArDate+  , ruleArInn+  , ruleCycleINdiaidhTime+  , ruleCycleInniu+  , ruleCycleRoimhTime+  , ruleCycleShin+  , ruleDNamedday+  , ruleDayofmonthOrdinal+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleIGceannCycle+  , ruleInn+  , ruleInniu+  , ruleIntersect+  , ruleIntersectBy+  , ruleLFhileBrde+  , ruleLFhilePdraig+  , ruleLFhileVailintn+  , ruleLNaNaithreacha+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNollaigNaMban+  , ruleOnANamedday+  , ruleOrdinalCycleDeTime+  , ruleOrdinalCycleINdiaidhTime+  , ruleOrdinalRithe+  , ruleOrdinalRitheYear+  , ruleTimeSeo+  , ruleTimeSeoChaite+  , ruleTimeSeoChugainn+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYyyymmdd+  ]
+ Duckling/Time/HE/Corpus.hs view
@@ -0,0 +1,292 @@+-- 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.Time.HE.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = HE}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "עכשיו"+             , "מייד"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "היום"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "אתמול"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "מחר"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "ראשון"+             , "יום ראשון"+             , "בראשון הזה"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "יום שני"+             , "שני"+             , "שני הזה"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             -- "שני השמונה עשרה לפברואר"+             [ "שני 18 לפברואר"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             -- "שלישי ה19"+             [ "שלישי"+             , "יום שלישי התשעה עשר"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "חמישי"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "שישי"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "שבת"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "ראשון"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             -- "הראשון למרץ"+             -- "ה1 למרץ"+             [ "1 למרץ"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "במרץ 3"+             ]+  , examples (datetime (2013, 3, 15, 0, 0, 0) Day)+             [ "באמצע מרץ"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             -- "השלישי למרץ 2015"+             [ "3 למרץ 2015"+             , "שלושה במרץ 2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             -- "חמש עשרה לחודש"+             -- "ב15 לחודש"+             -- "ב15 החודש"+             [+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "ה15 בפברואר"+             , "15 לפברואר"+             , "2/15"+             , "ב 2/15"+             , "פברואר 15"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "אוגוסט 8"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "אוקטובר 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "10/31/1974"+             , "10/31/74"+             , "10-31-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14 לאפריל 2015"+             , "אפריל 14, 2015"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "שישי הבא"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "מרץ הבא"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "ראשון, 10 לפברואר"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             -- "שני, השמונה עשרה לפברואר"+             -- "יום שני, ה18 לפברואר"+             [+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "בשבוע הזה"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "שבוע שעבר"+             , "שבוע האחרון"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "שבוע הבא"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "חודש שעבר"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "חודש הבא"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             -- "שנה שעברה"+             [+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "שנה הבאה"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "ראשון בשבוע שעבר"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "שלישי האחרון"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "רביעי שבוע הבא"+             , "רביעי הבא"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "שישי הבא"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "רביעי הזה"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "שני האחרון של מרץ"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "ראשון האחרון של מרץ 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "השלישי באוקטובר"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             -- "יום שלישי הראשון של אוקטובר"+             [+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18am"+             , "3:18a"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             -- "@ 3pm"+             [ "ב 3pm"+             , "3PM"+             , "3pm"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             -- "באיזור שלוש בצהריים"+             [+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             -- "3:15 בצהריים"+             -- "בשלוש ורבע בצהריים"+             [ "15:15"+             , "3:15pm"+             , "3:15PM"+             , "3:15p"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             -- "3:20 בצהריים"+             -- "3:20 צהריים"+             -- "עשרים אחרי שלוש בצהריים"+             [ "3:20p"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             -- "בשלוש וחצי בערב"+             -- "שלוש וחצי בצהריים"+             [ "15:30"+             , "3:30pm"+             , "3:30PM"+             , "330 p.m."+             , "3:30 p m"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "רבע ל12"+             , "11:45am"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             -- "בשבע וחצי בערב ביום שישי העשרים לספטמבר"+             [+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "בתשע בבוקר בשבת"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "שישי, יולי 18, 2014 07:00 PM"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "בעוד 2 דקות"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "בעוד 60 דקות"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "בעוד רבע שעה"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "בעוד חצי שעה"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "בעוד 24 שעות"+             , "בעוד עשרים וארבע שעות"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "בעוד שבעה ימים"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "לפני שבעה ימים"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             -- "לפני שלושה חודשים"+             [+             ]+  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "הערב"+             , "היום בערב"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "בסופ״ש האחרון"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "מחר בערב"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "מחר בצהריים"+             , "מחר צהריים"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "אתמול בערב"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "בסופ״ש הזה"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "שני בבוקר"+             ]+  ]
+ Duckling/Time/HE/Rules.hs view
@@ -0,0 +1,1556 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.HE.Rules+  ( rules ) where++import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Ordinal.Types (OrdinalData (..))+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.Ordinal.Types as TOrdinal+import qualified Duckling.TimeGrain.Types as TG+import qualified Duckling.Time.Types as TTime++ruleNextDayofweek :: Rule+ruleNextDayofweek = Rule+  { name = "next <day-of-week>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "(\x05d4\x05d1\x05d0(\x05d4)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "ב <named-day>"+  , pattern =+    [ regex "\x05d1"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleAtHourTimeofday :: Rule+ruleAtHourTimeofday = Rule+  { name = "at hour <time-of-day>"+  , pattern =+    [ regex "\x05d1\x05e9\x05e2\x05d4"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d3\x05e6\x05de\x05d1\x05e8"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleHourofdayAndInteger :: Rule+ruleHourofdayAndInteger = Rule+  { name = "<hour-of-day> and <integer>"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x05d5"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayAndQuarter :: Rule+ruleHourofdayAndQuarter = Rule+  { name = "<hour-of-day> and quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x05d5"+    , regex "\x05e8\x05d1\x05e2(\x05d9)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayAndHalf :: Rule+ruleHourofdayAndHalf = Rule+  { name = "<hour-of-day> and half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x05d5"+    , regex "\x05d7\x05e6\x05d9|\x05de\x05d7\x05e6\x05d9\x05ea"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHourofdayInteger :: Rule+ruleHourofdayInteger = Rule+  { name = "<hour-of-day> <integer>"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x05e8\x05d1\x05e2(\x05d9)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x05d7\x05e6\x05d9|\x05de\x05d7\x05e6\x05d9\x05ea"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleIntegerTotillbeforeIntegerHourofday :: Rule+ruleIntegerTotillbeforeIntegerHourofday = Rule+  { name = "<integer> to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "\x05dc\x05e4\x05e0\x05d9|\x05dc"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        tt t+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "\x05e8\x05d1\x05e2(\x05d9)?"+    , regex "\x05dc\x05e4\x05e0\x05d9|\x05dc"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "\x05d7\x05e6\x05d9|\x05de\x05d7\x05e6\x05d9\x05ea"+    , regex "\x05dc\x05e4\x05e0\x05d9|\x05dc"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleIntegerAfterpastIntegerHourofday :: Rule+ruleIntegerAfterpastIntegerHourofday = Rule+  { name = "integer after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesAfter n td+        tt t+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "\x05e8\x05d1\x05e2(\x05d9)?"+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Time td:_) -> Token Time <$> minutesAfter 15 td+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "\x05d7\x05e6\x05d9|\x05de\x05d7\x05e6\x05d9\x05ea"+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 30 td+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e9\x05e0\x05d9"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleSinceTimeofday :: Rule+ruleSinceTimeofday = Rule+  { name = "since <time-of-day>"+  , pattern =+    [ regex "\x05de"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ dimension Time+    , regex "\x05e9\x05e2\x05d1\x05e8|(\x05d4)?\x05e7\x05d5\x05d3\x05dd|(\x05d4)?\x05d0\x05d7\x05e8\x05d5\x05df"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e9\x05d9\x05e9\x05d9"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|\x05e2(\x05d3)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d9\x05d5\x05dc\x05d9"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleTheDayofmonthNonOrdinal :: Rule+ruleTheDayofmonthNonOrdinal = Rule+  { name = "the <day-of-month> (non ordinal)"+  , pattern =+    [ regex "\x05d4/S"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ dayOfMonth n+      _ -> Nothing+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "\x05d1\x05e2\x05d5\x05d3"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt $ inDuration dd+      _ -> Nothing+  }++ruleInNamedmonth :: Rule+ruleInNamedmonth = Rule+  { name = "in <named-month>"+  , pattern =+    [ regex "\x05d1"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "\x05e2\x05db\x05e9\x05d9\x05d5|\x05de\x05d9\x05d9\x05d3"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleCurrentDayofweek :: Rule+ruleCurrentDayofweek = Rule+  { name = "current <day-of-week>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "(\x05d4\x05d6\x05d4|\x05d4\x05d6\x05d0\x05ea|\x05d4\x05e7\x05e8\x05d5\x05d1(\x05d4)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "\x05de|\x05de\x05e9\x05e2\x05d4"+    , dimension Time+    , regex "\\-|\x05e2\x05d3"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e8\x05d1\x05d9\x05e2\x05d9"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ regex "\x05d4"+    , dimension TimeGrain+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ regex "\x05d4"+    , dimension TimeGrain+    , regex "\x05dc\x05e4\x05e0\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleLastDayofweek :: Rule+ruleLastDayofweek = Rule+  { name = "last <day-of-week>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "(\x05e9\x05e2\x05d1\x05e8(\x05d4)?|\x05d4\x05e7\x05d5\x05d3\x05de\x05ea|\x05d4\x05e7\x05d5\x05d3\x05dd)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "\x05d1\x05d0\x05de\x05e6\x05e2"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect td (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13)+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "(\x05d1)?\x05e6\x05d4\x05e8\x05d9\x05d9\x05dd"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "\x05d4\x05d9\x05d5\x05dd"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "\x05d1\x05d9\x05df"+    , Predicate isATimeOfDay+    , regex "\x05dc"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "\x05d4\x05d1\x05d0(\x05d4)?"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d9\x05e0\x05d5\x05d0\x05e8"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05de\x05e8\x05e5"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleForDuration :: Rule+ruleForDuration = Rule+  { name = "for <duration>"+  , pattern =+    [ regex "\x05ea\x05d5\x05da"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "\x05de\x05e2\x05db\x05e9\x05d9\x05d5"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(\x05d1)?\x05e6\x05d4\x05e8\x05d9\x05d9\x05dd"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 14)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "\x05d4\x05d0\x05d7\x05e8\x05d5\x05df|\x05d4\x05d0\x05d7\x05e8\x05d5\x05e0\x05d4|\x05e9\x05e2\x05d1\x05e8|\x05e9\x05e2\x05d1\x05e8\x05d4"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "\x05d0\x05d7\x05d4(\x05f4)?\x05e6|\x05d0\x05d7\x05e8 \x05d4\x05e6\x05d4\x05e8\x05d9\x05d9\x05dd"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 19)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d0\x05e4\x05e8\x05d9\x05dc"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05d7\x05de\x05d9\x05e9\x05d9"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "\x05d0\x05d7\x05e8\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "\x05d0\x05d7\x05e8\x05d9"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour True n+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "\x05e9\x05dc|\x05d1|\x05dc"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05e4\x05d1\x05e8\x05d5\x05d0\x05e8"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleThisEvening :: Rule+ruleThisEvening = Rule+  { name = "this evening"+  , pattern =+    [ regex "\x05d4\x05e2\x05e8\x05d1"+    ]+  , prod = \_ ->+      let td = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "\x05d1\x05d9\x05df"+    , dimension Time+    , regex "\x05dc"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleEndOfYear :: Rule+ruleEndOfYear = Rule+  { name = "End of year"+  , pattern =+    [ regex "\x05e1\x05d5\x05e3 (\x05d4)?\x05e9\x05e0\x05d4"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ regex "\x05dc\x05e4\x05e0\x05d9"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    , regex "\x05d0\x05d7\x05e8\x05d5\x05df|\x05d0\x05d7\x05e8\x05d5\x05e0\x05d5\x05ea|\x05d0\x05d7\x05e8\x05d5\x05e0\x05d4|\x05d0\x05d7\x05e8\x05d5\x05e0\x05d9\x05dd"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt . cycleN True grain $ - v+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "(\x05d1)?\x05d7\x05e6\x05d5\x05ea"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "\x05e2\x05d3"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "\x05d1"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d9\x05d5\x05e0\x05d9"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Time+    , dimension Ordinal+    , regex "\x05e9\x05dc|\x05d1"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Ordinal od:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d0\x05d5\x05d2\x05d5\x05e1\x05d8"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token Time pod:_) -> Token Time <$> intersect pod td+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "(\x05e1\x05d5\x05e4\x05f4\x05e9|\x05e1\x05d5\x05e3 \x05d4\x05e9\x05d1\x05d5\x05e2)"+    ]+  , prod = \_ -> do+      fri <- intersect (dayOfWeek 5) (hour False 18)+      mon <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (fri, mon)+  }++ruleNameddayDayofmonthOrdinal :: Rule+ruleNameddayDayofmonthOrdinal = Rule+  { name = "<named-day> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDate :: Rule+ruleDate = Rule+  { name = "ב <date>"+  , pattern =+    [ regex "\x05d1"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ Predicate isNotLatent+    , regex "\x05d4\x05d1\x05d0(\x05d4)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "\x05d4"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "\x05d0\x05d7\x05e8\x05d9|\x05dc\x05d0\x05d7\x05e8"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    , regex "\x05d4\x05d1\x05d0|\x05d4\x05d1\x05d0\x05d4|\x05d4\x05d1\x05d0\x05d9\x05dd|\x05d4\x05d1\x05d0\x05d5\x05ea"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "(\x05d1)?\x05d1\x05d5\x05e7\x05e8"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 4, hour False 12)+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "\x05d4\x05e7\x05e8\x05d5(\x05d1)?\x05d4|\x05d4\x05d6\x05d4|\x05d4\x05d6\x05d0\x05ea"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ dimension Time+    , regex "\x05d4\x05e7\x05e8\x05d5\x05d1|\x05d4\x05d6\x05d4"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "\x05e9\x05dc|\x05d1|\x05dc"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleEndOfMonth :: Rule+ruleEndOfMonth = Rule+  { name = "End of month"+  , pattern =+    [ regex "\x05e1\x05d5\x05e3 (\x05d4)?\x05d7\x05d5\x05d3\x05e9"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "(\x05d0\x05ea\x05de\x05d5\x05dc|\x05d0\x05de\x05e9)"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "\x05d0\x05d7\x05e8\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ dayOfMonth n+      _ -> Nothing+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(in the )?([ap])(\\s|\\.)?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (_:ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "\x05d0\x05d7\x05e8\x05d9|\x05dc\x05d0\x05d7\x05e8"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05de\x05d0\x05d9"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e9\x05d1\x05ea"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleTimeOfPartofday :: Rule+ruleTimeOfPartofday = Rule+  { name = "<time> of <part-of-day>"+  , pattern =+    [ dimension Time+    , regex "\x05d1"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05d0\x05d5\x05e7\x05d8\x05d5\x05d1\x05e8"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedday8 :: Rule+ruleNamedday8 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e8\x05d0\x05e9\x05d5\x05df"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "\x05d4\x05d0\x05d7\x05e8\x05d5\x05df \x05e9\x05dc"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleHhmmMilitaryAmpm :: Rule+ruleHhmmMilitaryAmpm = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):Token RegexMatch (GroupMatch (ap:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "\x05dc\x05e4\x05e0\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05e0\x05d5\x05d1\x05de\x05d1\x05e8"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "\x05d0\x05d7\x05e8\x05d9|\x05dc\x05d0\x05d7\x05e8"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleEveningnight :: Rule+ruleEveningnight = Rule+  { name = "evening|night"+  , pattern =+    [ regex "(\x05d1)?\x05e2\x05e8\x05d1"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 18, hour False 0)+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x05d9\x05d5\x05dd )?\x05e9\x05dc\x05d9\x05e9\x05d9"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleTheDayofmonthOrdinal :: Rule+ruleTheDayofmonthOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "\x05d4"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       _) -> tt $ dayOfMonth v+      _ -> Nothing+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "\x05dc\x05e4\x05e0\x05d9"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++rulePartofdayOfTime :: Rule+rulePartofdayOfTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ regex "\x05d1"+    , Predicate isAPartOfDay+    , regex "\x05e9\x05dc"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])[-/](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "(\x05de\x05d7\x05e8|\x05dc\x05de\x05d7\x05e8\x05ea)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "o.?clock"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x05e1\x05e4\x05d8\x05de\x05d1\x05e8"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:Token RegexMatch (GroupMatch (match:_)):_) -> do+        intVal <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year intVal)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterTimeofday+  , ruleAfternoon+  , ruleAtHourTimeofday+  , ruleAtTimeofday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleCurrentDayofweek+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDate+  , ruleDatetimeDatetimeInterval+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleEndOfMonth+  , ruleEndOfYear+  , ruleEveningnight+  , ruleForDuration+  , ruleFromDatetimeDatetimeInterval+  , ruleHhmm+  , ruleHhmmMilitaryAmpm+  , ruleHhmmss+  , ruleHourofdayAndInteger+  , ruleHourofdayAndQuarter+  , ruleHourofdayAndHalf+  , ruleHourofdayInteger+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleInDuration+  , ruleInNamedmonth+  , ruleIntersect+  , ruleIntersectBy+  , ruleLastCycle+  , ruleLastDayofweek+  , ruleLastDayofweekOfTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMorning+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedday8+  , ruleNameddayDayofmonthOrdinal+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNextCycle+  , ruleNextDayofweek+  , ruleNextNCycle+  , ruleNextTime+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeOfTime+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePartofdayOfTime+  , ruleIntegerAfterpastIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleIntegerTotillbeforeIntegerHourofday+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleSinceTimeofday+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheDayofmonthNonOrdinal+  , ruleTheDayofmonthOrdinal+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleThisCycle+  , ruleThisEvening+  , ruleThisTime+  , ruleTimeOfPartofday+  , ruleTimePartofday+  , ruleTimeofdayAmpm+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleToday+  , ruleTomorrow+  , ruleUntilTimeofday+  , ruleWeekend+  , ruleYear+  , ruleYesterday+  , ruleYyyymmdd+  ]
+ Duckling/Time/HR/Corpus.hs view
@@ -0,0 +1,671 @@+-- 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.Time.HR.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = HR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "sad"+             , "sada"+             , "upravo sad"+             , "ovaj tren"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "danas"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "jucer"+             , "jučer"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "sutra"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "ponedjeljak"+             , "pon."+             , "ovaj ponedjeljak"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "ponedjeljak, 18. veljace"+             , "ponedjeljak, 18. veljače"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "utorak"+             , "utorak 19."+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "cetvrtak"+             , "četvrtak"+             , "čet"+             , "cet."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "petak"+             , "pet"+             , "pet."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "subota"+             , "sub"+             , "sub."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "nedjelja"+             , "ned"+             , "ned."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1. ozujak"+             , "1. ožujak"+             , "prvi ozujka"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "treci ozujka"+             , "treci ožujka"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3. ozujka 2015"+             , "treci ozujka 2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15ti drugi"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15. veljace"+             , "15. veljače"+             , "15/02"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "8. kolovoza"+             , "8. kolovoz"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "listopad 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             , "74-10-31"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14travanj 2015"+             , "14. travnja, 2015"+             , "14. travanj 15"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "sljedeci utorak"+             , "sljedeceg utorka"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "petak nakon sljedeceg"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "sljedeci ozujak"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "ozujak nakon sljedeceg"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "nedjelja, 10. veljace"+             , "nedjelja, 10. veljače"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Sri, 13. velj"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "ponedjeljak, veljaca 18."+             , "Pon, 18. veljace"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "ovaj tjedan"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "prosli tjedan"+             , "prošli tjedan"+             , "prethodni tjedan"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "sljedeci tjedan"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "prethodni mjesec"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "sljedeci mjesec"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "ovaj kvartal"+             , "ovo tromjesecje"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "sljedeci kvartal"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "treci kvartal"+             , "3. kvartal"+             , "trece tromjesecje"+             , "3. tromjesečje"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4. kvartal 2018"+             , "četvrto tromjesečje 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "prošla godina"+             , "prethodna godina"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "ova godina"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "sljedece godina"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "prosle nedjelje"+             , "prosli tjedan u nedjelju"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "prosli utorak"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "sljedeci utorak"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "sljedecu srijedu"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "sljedeci tjedan u srijedu"+             , "srijeda sljedeci tjedan"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "sljedeci petak"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "ovaj tjedan u ponedjeljak"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "ovaj utorak"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "ova srijeda"+             , "ovaj tjedan u srijedu"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "prekosutra"+             ]+  , examples (datetime (2013, 2, 14, 17, 0, 0) Hour)+             [ "prekosutra u 5 popodne"+             , "prekosutra u 17"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "prekjucer"+             , "prekjučer"+             ]+  , examples (datetime (2013, 2, 10, 8, 0, 0) Hour)+             [ "prekjučer u 8"+             , "prekjučer u 8 sati"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "zadnji ponedjeljak u ozujku"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "zadnja nedjelja u ozujku 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "treci dan u listopadu"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "prvi tjedan u listopadu 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "zadnji dan u listopadu 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "zadnji tjedan u rujnu 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "prvi utorak u listopadu"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "treci utorak u rujnu 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "prva srijeda u listopadu 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "druga srijeda u listopadu 2014"+             ]+  , examples (datetime (2015, 1, 13, 0, 0, 0) Day)+             [ "treci utorak poslije Bozica 2014"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "3 u noci"+             , "u 3 ujutro"+             , "u tri sata u noci"+             ]+  , examples (datetime (2013, 2, 12, 3, 18, 0) Minute)+             [ "3:18 rano"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "u 3 poslijepodne"+             , "@ 15"+             , "15 sati poslijepodne"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "oko 3 poslijepodne"+             , "otprilike u 3 poslijepodne"+             , "cca 3 poslijepodne"+             , "cca 15"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "15 i 15"+             , "3:15 poslijepodne"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "cetvrt nakon 3 poslijepodne"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "3 i 20 popodne"+             , "3:20 poslijepodne"+             , "3:20 popodne"+             , "dvadeset nakon 3 popodne"+             , "15:20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "tri i po popodne"+             , "pola 4 popodne"+             , "15:30"+             , "pola cetiri popodne"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "petnaest do podne"+             , "11:45"+             , "četvrt do podneva"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 navecer"+             , "osam sati navecer"+             , "danas 8 navecer"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "u 7:30 popodne u pet, 20. rujna"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "9 ujutro u subotu"+             , "u subotu u 9 sati ujutro"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "pet, srp 18., 2014, 19:00"+             , "pet, srp 18., 2014 u 19:00"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "za jednu sekundu"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "za jednu minutu"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "za 2 minute"+             , "za jos 2 minute"+             , "2 minute od sad"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "za 60 minuta"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "oko cetvrt sata"+             , "oko 1/4h"+             , "oko 1/4 h"+             , "oko 1/4 sata"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "za pola sata"+             , "za pol sata"+             , "za 1/2h"+             , "za 1/2 h"+             , "za 1/2 sata"+             ]+  , examples (datetime (2013, 2, 12, 5, 15, 0) Second)+             [ "za tri-cetvrt sata"+             , "za 3/4h"+             , "za 3/4 h"+             , "za 3/4 sata"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "za 2.5 sata"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "za jedan sat"+             , "za 1h"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "za par sati"+             ]+  , examples (datetime (2013, 2, 12, 7, 30, 0) Minute)+             [ "za nekoliko sati"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "za 24 sata"+             , "za 24h"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "za 1 dan"+             , "za jedan dan"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ "3 godine od danasnjeg dana"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "za 7 dana"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "za 1 tjedan"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "za oko pola sata"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "prije 7 dana"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "prije 14 dana"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "prije jedan tjedan"+             , "prije jednog tjedna"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "prije tri tjedna"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "prije tri mjeseca"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "prije dvije godine"+             ]+  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "za 7 dana"+             ]+  , examples (datetime (2013, 2, 26, 4, 0, 0) Hour)+             [ "za 14 dana"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "za jedan tjedan"+             ]+  , examples (datetime (2013, 3, 5, 0, 0, 0) Day)+             [ "za tri tjedna"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "za tri mjeseca"+             ]+  , examples (datetime (2015, 2, 0, 0, 0, 0) Month)+             [ "za dvije godine"+             ]+  , examples (datetime (2013, 12, 0, 0, 0, 0) Month)+             [ "jednu godinu poslije Bozica"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "ovog ljeta"+             , "ovo ljeto"+             , "ljetos"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "ove zime"+             , "zimus"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "Bozic"+             , "zicbo"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "stara godina"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "nova godina"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "valentinovo"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "majcin dan"+             ]+  , examples (datetime (2013, 6, 16, 0, 0, 0) Day)+             [ "dan oceva"+             ]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "noc vjestica"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "veceras"+             , "ove veceri"+             , "danas navecer"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "prosli vikend"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "sutra navecer"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "sutra rucak"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "jucer navecer"+             , "prethodne veceri"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "ovaj vikend"+             , "ovog vikenda"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "ponedjeljak ujutro"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 3, 0, 0), (2013, 2, 18, 9, 0, 0)) Hour)+             [ "ponedjeljak rano ujutro"+             , "ponedjeljak rano"+             , "ponedjeljak u rane jutarnje sate"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "15. veljace ujutro"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "prosle 2 sekunde"+             , "prethodne dvije sekunde"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "sljedece 3 sekunde"+             , "sljedece tri sekunde"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "prosle 2 minute"+             , "prethodne dvije minute"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "sljedece 3 minute"+             , "sljedece tri minute"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "prethodni jedan sat"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 4, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "prethodna 24 sata"+             , "prethodna dvadeset i cetiri sata"+             , "prethodna dvadeset i cetiri sata"+             , "prethodna 24h"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "sljedeca 3 sata"+             , "sljedeca tri sata"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "prethodna dva dana"+             , "prethodna 2 dana"+             , "prosla 2 dana"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "sljedeca 3 dana"+             , "sljedeca tri dana"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "sljedecih nekoliko dana"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "prethodna 2 tjedna"+             , "prethodna dva tjedna"+             , "prosla 2 tjedna"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "sljedeca 3 tjedna"+             , "sljedeca tri tjedna"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "prethodna 2 mjeseca"+             , "prethodna dva mjeseca"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "sljedeca 3 mjeseca"+             , "sljedeca tri mjeseca"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "prethodne 2 godine"+             , "prethodne dvije godine"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "sljedece 3 godine"+             , "sljedece tri godine"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "srpanj 13-15"+             , "srpanj 13 do 15"+             , "srpanj 13 - srpanj 15"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "kol 8 - kol 12"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "od 9:30 - 11:00 u cetvrtak"+             , "između 9:30 i 11:00 u cetvrtak"+             , "9:30 - 11:00 u cetvrtak"+             , "izmedju 9:30 i 11:00 u cetvrtak"+             , "cetvrtak od 9:30 do 11:00"+             , "od 9:30 do 11:00 u cetvrtak"+             , "cetvrtak od 9:30 do 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "cetvrtak od 9 do 11 ujutro"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-1:30"+             ]+  , examples (datetime (2013, 9, 21, 13, 30, 0) Minute)+             [ "1:30 poslijepodne u sub, ruj 21."+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 4, 0, 0, 0)) Week)+             [ "sljedeca 2 tjedna"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "nekad do 2 poslijepodne"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 13, 0, 0, 0)) Second)+             [ "do kraja ovog dana"+             , "do kraja dana"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 3, 1, 0, 0, 0)) Second)+             [ "do kraja ovog mjeseca"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 4, 1, 0, 0, 0)) Second)+             [ "do kraja sljedeceg mjeseca"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "4 poslijepodne CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "cetvrtak 8:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "danas u 14"+             , "u 2 poslijepodne"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Hour)+             [ "25/4 U 16 sati"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "15 sati sutra"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "nakon 5 dana"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "prije 11 sat"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 20, 0, 0)) Hour)+             [ "ova poslijepodne"+             , "ovi popodne"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "u 13:30"+             , "13:30"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "za 15 minuta"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "poslije rucka"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "ove jutro"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "sljedeci ponedjeljak"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "u 12"+             , "u podne"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "u 12 u noci"+             , "u ponoc"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "ozujak"+             , "u ozujku"+             ]+  ]
+ Duckling/Time/HR/Rules.hs view
@@ -0,0 +1,1898 @@+-- 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 #-}++module Duckling.Time.HR.Rules+  ( rules ) where++import Control.Monad (join, liftM2)+import Data.Maybe+import Data.String+import Data.Text (Text)+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Types (NumeralData (..))+import Duckling.Ordinal.Types (OrdinalData (..))+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.Ordinal.Types as TOrdinal+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "ponedjelja?ka?|pon\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 1+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "prosina?c(a|u)?|decemba?r(a|u)?|dec\\.?|pros?\\.?|dvanaest(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 12+  }++ruleHalfIntegerHrStyleHourofday :: Rule+ruleHalfIntegerHrStyleHourofday = Rule+  { name = "half <integer> (HR style hour-of-day)"+  , pattern =+    [ regex "pol?a?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleNumeralTotillbeforeIntegerHourofday :: Rule+ruleNumeralTotillbeforeIntegerHourofday = Rule+  { name = "numeral to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "do"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "(kvarata?|(c|\x010d)etvrt|frtalj)\\s+do"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "di pol?a?\\s+do"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleNumeralAfterpastHourofday :: Rule+ruleNumeralAfterpastHourofday = Rule+  { name = "numeral after|past (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "poslije|nakon"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesAfter n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleQuarterAfterpastHourofday :: Rule+ruleQuarterAfterpastHourofday = Rule+  { name = "quarter after|past (hour-of-day)"+  , pattern =+    [ regex "(kvarata?|(c|\x010d)etvrt|frtalj)\\s+(poslije|nakon)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 15 td+      _ -> Nothing+  }++ruleHalfAfterpastHourofday :: Rule+ruleHalfAfterpastHourofday = Rule+  { name = "half after|past (hour-of-day)"+  , pattern =+    [ regex "(i pol?a?)\\s+(poslije|nakon)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesAfter 30 td+      _ -> Nothing+  }++ruleHourofdayNumeral :: Rule+ruleHourofdayNumeral = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "kvarata?|(c|\x010d)etvrt|frtalj"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "i pol?a?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleZaNumeralHourofday :: Rule+ruleZaNumeralHourofday = Rule+  { name = "za <integer> (hour-of-day)"+  , pattern =+    [ regex "za"+    , Predicate $ isIntegerBetween 1 59+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       token:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleZaQuarterHourofday :: Rule+ruleZaQuarterHourofday = Rule+  { name = "za quarter (hour-of-day)"+  , pattern =+    [ regex "za\\s+(kvarata?|(c|\x010d)etvrt|frtalj)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleZaHalfHourofday :: Rule+ruleZaHalfHourofday = Rule+  { name = "za half (hour-of-day)"+  , pattern =+    [ regex "za\\s+(i pol?a?)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "utora?ka?|uto?\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "valentinov(og?|a|)"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 2 14+  }++ruleSinceTimeofday :: Rule+ruleSinceTimeofday = Rule+  { name = "since <time-of-day>"+  , pattern =+    [ regex "od"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "nov(a|u|e) godin(a|e|u)"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(prethodn(i|u|a|e|o(ga?)?)|pro(s|\x0161)l(ih?|u|a|e|o(ga?)?))"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Just . Token Time $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "subot(a|e|u)|sub?\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "srpa?nj(a|u)?|jul(i|u|a)?|jul\\.?|srp\\.?|sedm(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 7+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "nakon"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        Just . Token Time $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "za"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> Just . Token Time $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "((upravo|ov(aj?|og?|e|i))? ?sada?|trenutak|upravo|trenutno)|(ov(aj|og) trena?)"+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "zadnj(ih?|a|e(ga?)?)"+    , dimension TimeGrain+    , regex "u"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        Just . Token Time $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "od|izme(dj|\x0111)u"+    , dimension Time+    , regex "\\-"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ Predicate isAMonth+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|do"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        from <- intersect (dayOfMonth d1) td+        to <- intersect (dayOfMonth d2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x010d|c)etvrta?ka?|(\x010d|c)et\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 4+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "prolje(c|\x0107)(e|a)"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 3 20, monthDay 6 21)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ dimension Time+    , regex "nakon sljede(\x0107|c)(i|e|a)(ga?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Just . Token Time $ predNth 1 True td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "(u )?podne(va)?"+    ]+  , prod = \_ -> Just . Token Time $ hour False 12+  }++ruleEarlyMorning :: Rule+ruleEarlyMorning = Rule+  { name = "early morning"+  , pattern =+    [ regex "(rano( (u )?u?jutros?)?)|(u ran(im|e) jutarnj(im|e) sat(ima|e))"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 3, hour False 9)+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "danas?|(dana(s|\x0161)nj(i|eg) dana?) "+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "ov(aj?|og?|e)|sljede(c|\x0107)(i|u|a|e(ga?)?)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ predNth 0 True td+      _ -> Nothing+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "od|izme(dj|\x0111)u"+    , Predicate isATimeOfDay+    , regex "do|i"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "sljede(c|\x0107)(i|a|u|e(ga?)?)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Time $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "sije(c|\x010d)a?nj(a|u)?|januar(a|u)?|jan\\.?|sij?\\.?|prv(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 1+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(-?ak)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "o(z|\x017e)uja?k(a|u)?|mart(a|u)?|mar\\.?|o(z|\x017e)u?\\.?|tre(c|\x0107)(i|a|e(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 3+  }++ruleForDuration :: Rule+ruleForDuration = Rule+  { name = "for <duration>"+  , pattern =+    [ regex "za( jo(s|\x0161))?|u"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> Just . Token Time $ inDuration dd+      _ -> Nothing+  }++ruleLastDayofweekTime :: Rule+ruleLastDayofweekTime = Rule+  { name = "last <day-of-week> <time>"+  , pattern =+    [ regex "zadnj(ih?|a|e(ga?)?)"+    , Predicate isADayOfWeek+    , regex "u"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ predLastOf td1 td2+      _ -> Nothing+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "od (sada?|ovog trenutka|dana(s|\x0161)nj(i|eg) dana?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) -> Just . Token Time $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(((za )|(u vrijeme )) )?ru(c|\x010d)a?k(a|om)?"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 14)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "prethodn(i|a|e|u)|pro(s|\x0161)l(i|a|e|u|o(ga?)?)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Time . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd.mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])\\/(0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        d <- parseInt dd+        m <- parseInt mm+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "po(slije)?podne"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 20)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "trava?nj(a|u)?|april(a|u)?|apr\\.?|tra\\.?|(\x010d|c)etvrt(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ dimension Time+    , regex "prije (prethodn(e|o(ga?)?)|pro(s|\x0161)l(ih?|u|a|e|o(ga?)?))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        Just . Token Time $ predNth (-2) False td+      _ -> Nothing+  }++ruleLateNight :: Rule+ruleLateNight = Rule+  { name = "late night"+  , pattern =+    [ regex "(((u|po)\\s)?no(c|\x0107)(i|as|u)?|u?jutros?)"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 0, hour False 4)+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "badnjaka?"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "(u|tokom)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ notLatent td+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "peta?ka?|pet\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "poslije|nakon|iza"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "(nakon|poslije)( jo(s|\x0161))?"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour True n+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "of|in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "od"+    , Predicate isATimeOfDay+    , regex "\\-"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "(ve)?lja(c|\x010d)(a|e|i)|februar(a|u)?|feb\\.?|ve(lj)?\\.?|drug(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "to(c|\x010d)no( u)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "zim(a|e|us)?"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 12 21, monthDay 3 20)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "ljet(os?|a)"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 6 21, monthDay 9 23)+  }++ruleUNamedday :: Rule+ruleUNamedday = Rule+  { name = "u <named-day>"+  , pattern =+    [ regex "u"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "od|izme(dj|\x0111)u"+    , dimension Time+    , regex "do|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "star(a|u|e) godin(a|e|u)"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 12 31+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "(do )(kraja|isteka)? "+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "poslije (posla|kraja radnog vremena)"+    ]+  , prod = \_ -> Token Time . partOfDay . notLatent <$>+      intersect (cycleNth TG.Day 0)+      (interval TTime.Open (hour False 17, hour False 21))+  }++ruleLastDayofweekTime2 :: Rule+ruleLastDayofweekTime2 = Rule+  { name = "last <day-of-week> <time>"+  , pattern =+    [ regex "zadnj(ih?|a|e(ga?)?)"+    , Predicate isADayOfWeek+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:Token Time td2:_) ->+        Just . Token Time $ predLastOf td1 td2+      _ -> Nothing+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "prethodn(ih?|a|e)|pro(s|\x0161)l(a|e|ih?)"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleN True grain $ - n+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "(u|za )vrijeme"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "(u )?pono(c|\x0107)i?|(the )?(EOD|((do )? kraja? dana))"+    ]+  , prod = \_ -> Just . Token Time $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(oko|cca|otprilike)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "((nekad|najkasnije) )?(prije|do)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "u|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "lipa?nj(a|u)?|jun(i|u|a)?|jun\\.?|lip?\\.?|(\x0161|s)est(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "u"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "kolovoz(a|u)?|august(a|u)?|aug\\.?|kol\\.?|osm(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token Time pod:_) -> Token Time <$> intersect pod td+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "(za )?vikenda?"+    ]+  , prod = \_ -> do+      fri <- intersect (dayOfWeek 5) (hour False 18)+      mon <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (fri, mon)+  }++rulePrijeDuration :: Rule+rulePrijeDuration = Rule+  { name = "prije <duration>"+  , pattern =+    [ regex "prije"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> Just . Token Time $ durationAgo dd+      _ -> Nothing+  }++ruleAboutDuration :: Rule+ruleAboutDuration = Rule+  { name = "about <duration>"+  , pattern =+    [ regex "oko"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> Just . Token Time $ inDuration dd+      _ -> Nothing+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "(the )?(EOM|(do )? kraja mjeseca)"+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Month 1+  }++ruleNameddayDayofmonthOrdinal :: Rule+ruleNameddayDayofmonthOrdinal = Rule+  { name = "<named-day> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "sljede(c|\x0107)(i|u|a|e(ga?)?)"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (n - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "(u )?(sljede(c|\x0107)(ih?|a|eg?))"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt $ cycleN True grain n+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "(u )?u?jutros?"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 4, hour False 12)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "ov(aj?|og?|i|e)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay . notLatent <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "ov(aj?|og?|e|i)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> Just . Token Time $ cycleNth grain 0+      _ -> Nothing+  }++ruleUNamedmonth :: Rule+ruleUNamedmonth = Rule+  { name = "u <named-month>"+  , pattern =+    [ regex "u"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "ov(aj?|og?|e)(sad)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ predNth 0 False td+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "of|in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears :: Rule+ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears = Rule+  { name = "hhmm (military, prefixed with m to avoid ambiguity with years)"+  , pattern =+    [ regex "m((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ timeOfDayAMPM (hourMinute False h m) False+      _ -> Nothing+  }++ruleDayBeforeYesterday :: Rule+ruleDayBeforeYesterday = Rule+  { name = "day before yesterday"+  , pattern =+    [ regex "(prekju(c|\x010d)er)"+    ]+  , prod = \_ -> Just . Token Time . cycleNth TG.Day $ - 2+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "poslije ru(c|\x010d)ka"+    ]+  , prod = \_ -> Token Time . partOfDay . notLatent <$>+      intersect (cycleNth TG.Day 0)+      (interval TTime.Open (hour False 13, hour False 17))+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $+       liftM2 (||) (isIntegerBetween (- 10000) 0) (isIntegerBetween 25 999)+    ]+  , prod = \tokens -> case tokens of+     (token:_) -> do+       n <- getIntValue token+       tt . mkLatent $ year n+     _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "(ju(c|\x010d)er)"+    ]+  , prod = \_ -> Just . Token Time . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "jesen(i|as)?"+    ]+  , prod = \_ ->+      tt $ interval TTime.Open (monthDay 9 23, monthDay 12 21)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "(nekad |najranije )?(prije|od)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "(zi(c|\x0107)bo|bo(z|\x017e)i(c|\x0107))(a|u|ni|na)?"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 12 25+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month>. (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "\\.|i|og"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "nakon"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        Just . Token Time $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "od|u"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        Just . Token Time $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleAfterNextTime :: Rule+ruleAfterNextTime = Rule+  { name = "after next <time>"+  , pattern =+    [ regex "nakon sljede(\x0107|c)(i|e|a)(ga?)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ predNth 1 True td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "sviba?nj(a|u)?|maj|svi\\.?|pet(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "nedjelj(a|e|u)|ned\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 7+  }++ruleDayAfterTomorrow :: Rule+ruleDayAfterTomorrow = Rule+  { name = "day after tomorrow"+  , pattern =+    [ regex "(preko?sutra)"+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Day 2+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[(:.\\si]+([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "(na)?ve(c|\x010d)er(as)?"+    ]+  , prod = \_ ->+      let today = cycleNth TG.Day 0+          evening = interval TTime.Open (hour False 18, hour False 0) in+        Token Time . partOfDay . notLatent <$> intersect today evening+  }++ruleBeforeLasttime :: Rule+ruleBeforeLasttime = Rule+  { name = "before last<time>"+  , pattern =+    [ regex "prije (prethodn(i|u|a|e|o(ga?)?)|pro(s|\x0161)l(ih?|a|e|o(ga?)?))"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Just . Token Time $ predNth (-2) False td+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) (isGrainFinerThan TG.Day) isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "listopad(a|u)?|oktobar(a|u)?|okt\\.?|lis\\.?|deset(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "no(c|\x0107) vje(s|\x0161)tica"+    ]+  , prod = \_ -> Just . Token Time $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleFathersDay :: Rule+ruleFathersDay = Rule+  { name = "Father's Day"+  , pattern =+    [ regex "dan (o(c|\x010d)eva|tata)"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 2 7 6+  }++ruleByTime :: Rule+ruleByTime = Rule+  { name = "by <time>"+  , pattern =+    [ regex "do"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ interval TTime.Open (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "prije"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        Just . Token Time $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/](0?[1-9]|1[0-2])[\\/](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isNotLatent isATimeOfDay+    , regex "\\-|:"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Just . Token Time $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "studen(i|oga?|om)|novemba?r(a|u)?|nov\\.?|stu\\.?|jedanaest(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "nakon|poslije|od"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        Just . Token Time $ durationAfter dd td+      _ -> Nothing+  }++ruleEveningnight :: Rule+ruleEveningnight = Rule+  { name = "evening|night"+  , pattern =+    [ regex "(na)?ve(c|\x010d)er(i|as)?"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 18, hour False 0)+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleDayBeforeDayBeforeYesterday :: Rule+ruleDayBeforeDayBeforeYesterday = Rule+  { name = "day before day before yesterday"+  , pattern =+    [ regex "(prek\\s?prekju(c|\x010d)er)"+    ]+  , prod = \_ -> Just . Token Time . cycleNth TG.Day $ - 3+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "srijed(a|e|u)|sri\\.?"+    ]+  , prod = \_ -> Just . Token Time $ dayOfWeek 3+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "prije"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        Just . Token Time $ durationBefore dd td+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "(the )?(EOY|(do )? kraja? godine)"+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "(sutra(dan)?)"+    ]+  , prod = \_ -> Just . Token Time $ cycleNth TG.Day 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "maj(c|\x010d)in dan"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "sat(i|a)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Just . Token Time $ notLatent td+      _ -> Nothing+  }++ruleYear2 :: Rule+ruleYear2 = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isOrdinalBetween 1000 2100+    , regex "\\.|e"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "ruja?n(a|u)?|septemba?r(a|u)?|sept?\\.?|ruj\\.?|devet(i|a|o(ga?)?)"+    ]+  , prod = \_ -> Just . Token Time $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:Token RegexMatch (GroupMatch (match:_)):_) -> do+        intVal <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year intVal)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutDuration+  , ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterLunch+  , ruleAfterNextTime+  , ruleAfterTimeofday+  , ruleAfterWork+  , ruleAfternoon+  , ruleAtTimeofday+  , ruleBeforeLasttime+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleByTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayAfterTomorrow+  , ruleDayBeforeDayBeforeYesterday+  , ruleDayBeforeYesterday+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDurationAfterTime+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleEarlyMorning+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEveningnight+  , ruleExactlyTimeofday+  , ruleFathersDay+  , ruleForDuration+  , ruleFromDatetimeDatetimeInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalfIntegerHrStyleHourofday+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears+  , ruleHhmmss+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleIntersect+  , ruleIntersectBy+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastDayofweekTime+  , ruleLastDayofweekTime2+  , ruleLastNCycle+  , ruleLastTime+  , ruleLateNight+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNameddayDayofmonthOrdinal+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeOfTime+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePrijeDuration+  , ruleNumeralAfterpastHourofday+  , ruleQuarterAfterpastHourofday+  , ruleHalfAfterpastHourofday+  , ruleNumeralTotillbeforeIntegerHourofday+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleHourofdayNumeral+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleSinceTimeofday+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimezone+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleTonight+  , ruleUNamedday+  , ruleUNamedmonth+  , ruleUntilTimeofday+  , ruleValentinesDay+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYear2+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleZaNumeralHourofday+  , ruleZaQuarterHourofday+  , ruleZaHalfHourofday+  ]
+ Duckling/Time/Helpers.hs view
@@ -0,0 +1,508 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.Helpers+  ( -- Patterns+    isADayOfWeek, isAMonth, isAnHourOfDay, isAPartOfDay, isATimeOfDay+  , isDOMInteger, isDOMOrdinal, isDOMValue, isGrain, isGrainFinerThan+  , isGrainOfTime, isIntegerBetween, isNotLatent, isOrdinalBetween+  , isMidnightOrNoon+    -- Production+  , cycleLastOf, cycleN, cycleNth, cycleNthAfter, dayOfMonth, dayOfWeek+  , daysOfWeekOfMonth, durationAfter, durationAgo, durationBefore, form, hour+  , hourMinute, hourMinuteSecond, inDuration, intersect, intersectDOM, interval+  , inTimezone, longWEBefore, minute, minutesAfter, minutesBefore, mkLatent+  , month, monthDay, notLatent, nthDOWOfMonth, partOfDay, predLastOf, predNth+  , predNthAfter, second, timeOfDayAMPM, withDirection, year, yearMonthDay+  , tt+    -- Other+  , getIntValue+  ) where++import Control.Monad (liftM2)+import Data.Maybe+import Prelude+import Data.Text (Text)+import qualified Data.Time as Time+import qualified Data.Time.Calendar.WeekDate as Time+import qualified Data.Time.LocalTime.TimeZone.Series as Series++import Duckling.Dimensions.Types+import Duckling.Duration.Types (DurationData (DurationData))+import qualified Duckling.Duration.Types as TDuration+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Ordinal.Types (OrdinalData (OrdinalData))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Time.TimeZone.Parse (parseTimezone)+import Duckling.Time.Types+  ( TimeData(TimeData)+  , mkSeriesPredicate+  , mkSecondPredicate+  , mkMinutePredicate+  , mkHourPredicate+  , mkAMPMPredicate+  , mkMonthPredicate+  , mkDayOfTheWeekPredicate+  , mkDayOfTheMonthPredicate+  , mkYearPredicate+  , mkIntersectPredicate+  , mkTimeIntervalsPredicate+  , runPredicate+  , AMPM(..)+  )+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++getIntValue :: Token -> Maybe Int+getIntValue (Token Numeral nd) = TNumeral.getIntValue $ TNumeral.value nd+getIntValue (Token Ordinal OrdinalData {TOrdinal.value = x}) = Just x+getIntValue _ = Nothing++timeNegPeriod :: DurationData -> DurationData+timeNegPeriod (DurationData v g) = DurationData+  {TDuration.grain = g, TDuration.value = negate v}++-- -----------------------------------------------------------------+-- Time predicates++timeCycle :: TG.Grain -> TTime.Predicate+timeCycle grain = mkSeriesPredicate series+  where+  series t _ = TTime.timeSequence grain 1 $ TTime.timeRound t grain++timeSecond :: Int -> TTime.Predicate+timeSecond n = mkSecondPredicate n++timeMinute :: Int -> TTime.Predicate+timeMinute n = mkMinutePredicate n++timeHour :: Bool -> Int -> TTime.Predicate+timeHour is12H n = mkHourPredicate is12H n++timeDayOfWeek :: Int -> TTime.Predicate+timeDayOfWeek n = mkDayOfTheWeekPredicate n++timeDayOfMonth :: Int -> TTime.Predicate+timeDayOfMonth n = mkDayOfTheMonthPredicate n++timeMonth :: Int -> TTime.Predicate+timeMonth n = mkMonthPredicate n++-- | Converts 2-digits to a year between 1950 and 2050+timeYear :: Int -> TTime.Predicate+timeYear n = mkYearPredicate n++-- | Takes `n` cycles of `f`+takeN :: Int -> Bool -> TTime.Predicate -> TTime.Predicate+takeN n notImmediate f = mkSeriesPredicate series+  where+  series t context =+    case slot of+      Just nth -> if TTime.timeStartsBeforeTheEndOf t nth+        then ([], [nth])+        else ([nth], [])+      Nothing -> ([], [])+    where+      baseTime = TTime.refTime context+      (past, future) = runPredicate f baseTime context+      fut = case future of+        (ahead:rest)+          | notImmediate && isJust (TTime.timeIntersect ahead baseTime) -> rest+        _ -> future+      slot = if n >= 0+        then case fut of+          (start:_) -> case drop n fut of+            (end:_) -> Just $ TTime.timeInterval TTime.Open start end+            _ -> Nothing+          _ -> Nothing+        else case past of+          (end:_) -> case drop ((- n) - 1) past of+            (start:_) -> Just $ TTime.timeInterval TTime.Closed start end+            _ -> Nothing+          _ -> Nothing++-- | -1 is the first element in the past+-- | 0 is the first element in the future+takeNth :: Int -> Bool -> TTime.Predicate -> TTime.Predicate+takeNth n notImmediate f = mkSeriesPredicate series+  where+  series t context =+    case rest of+      [] -> ([], [])+      (nth:_) -> if TTime.timeStartsBeforeTheEndOf t nth+        then ([], [nth])+        else ([nth], [])+    where+      baseTime = TTime.refTime context+      (past, future) = runPredicate f baseTime context+      rest = if n >= 0+        then case future of+          (ahead:_) | notImmediate && isJust (TTime.timeIntersect ahead baseTime)+            -> drop (n + 1) future+          _ -> drop n future+        else drop (- (n + 1)) past++-- | Like `takeNth`, but takes the nth cyclic predicate after `basePred`+takeNthAfter+  :: Int+  -> Bool+  -> TTime.Predicate+  -> TTime.Predicate+  -> TTime.Predicate+takeNthAfter n notImmediate cyclicPred basePred =+  mkSeriesPredicate $! TTime.timeSeqMap False f basePred+  where+    f t ctx =+      let (past, future) = runPredicate cyclicPred t ctx+          rest = if n >= 0+                   then case future of+                     (ahead:_) | notImmediate && TTime.timeBefore ahead t+                       -> drop (n + 1) future+                     _ -> drop n future+                   else drop (- (n + 1)) past+      in case rest of+           [] -> Nothing+           (nth:_) -> Just nth++-- | Takes the last occurrence of `cyclicPred` within `basePred`.+takeLastOf :: TTime.Predicate -> TTime.Predicate -> TTime.Predicate+takeLastOf cyclicPred basePred =+  mkSeriesPredicate $! TTime.timeSeqMap False f basePred+  where+    f :: TTime.TimeObject -> TTime.TimeContext -> Maybe TTime.TimeObject+    f t ctx =+      case runPredicate cyclicPred (TTime.timeStartingAtTheEndOf t) ctx of+        (nth:_, _) -> Just nth+        _ -> Nothing++-- | Assumes the grain of `pred1` is smaller than the one of `pred2`+timeCompose :: TTime.Predicate -> TTime.Predicate -> TTime.Predicate+timeCompose pred1 pred2 = mkIntersectPredicate pred1 pred2++shiftDuration :: TTime.Predicate -> DurationData -> TTime.Predicate+shiftDuration pred1 (DurationData n g) =+  mkSeriesPredicate $! TTime.timeSeqMap False f pred1+  where+    grain = case g of+      TG.Second -> TG.Second+      TG.Year -> TG.Month+      TG.Month -> TG.Day+      _ -> pred g+    f x _ = Just $ TTime.timePlus (TTime.timeRound x grain) g $ toInteger n++shiftTimezone :: Series.TimeZoneSeries -> TTime.Predicate -> TTime.Predicate+shiftTimezone providedSeries pred1 =+  mkSeriesPredicate $! TTime.timeSeqMap False f pred1+  where+    f x@(TTime.TimeObject s _ _) ctx =+      let Time.TimeZone ctxOffset _ _ =+            Series.timeZoneFromSeries (TTime.tzSeries ctx) s+          Time.TimeZone providedOffset _ _ =+            Series.timeZoneFromSeries providedSeries s+      -- This forgets about TTime.end, but it's OK since we act on time-of-days.+      in Just . TTime.timePlus x TG.Minute . toInteger $+           ctxOffset - providedOffset++-- -----------------------------------------------------------------+-- Patterns++isGrain :: TG.Grain -> Predicate+isGrain value (Token TimeGrain grain) = grain == value+isGrain _ _ = False++isGrainFinerThan :: TG.Grain -> Predicate+isGrainFinerThan value (Token Time (TimeData {TTime.timeGrain = g})) = g < value+isGrainFinerThan _ _ = False++isGrainOfTime :: TG.Grain -> Predicate+isGrainOfTime value (Token Time (TimeData {TTime.timeGrain = g})) = g == value+isGrainOfTime _ _ = False++isADayOfWeek :: Predicate+isADayOfWeek (Token Time td) = case TTime.form td of+  Just TTime.DayOfWeek -> True+  _ -> False+isADayOfWeek _ = False++isATimeOfDay :: Predicate+isATimeOfDay (Token Time td) = case TTime.form td of+  Just (TTime.TimeOfDay _ _) -> True+  _ -> False+isATimeOfDay _ = False++isAPartOfDay :: Predicate+isAPartOfDay (Token Time td) = case TTime.form td of+  Just TTime.PartOfDay -> True+  _ -> False+isAPartOfDay _ = False++isAMonth :: Predicate+isAMonth (Token Time td) = case TTime.form td of+  Just (TTime.Month _) -> True+  _ -> False+isAMonth _ = False++isAnHourOfDay :: Predicate+isAnHourOfDay (Token Time td) = case TTime.form td of+  Just (TTime.TimeOfDay (Just _) _) | TTime.timeGrain td > TG.Minute -> True+  _ -> False+isAnHourOfDay _ = False++isMidnightOrNoon :: Predicate+isMidnightOrNoon (Token Time td) = case TTime.form td of+  Just (TTime.TimeOfDay (Just x) _) -> x == 0 || x == 12+  _ -> False+isMidnightOrNoon _ = False++isNotLatent :: Predicate+isNotLatent (Token Time td) = not $ TTime.latent td+isNotLatent _ = False++isIntegerBetween :: Int -> Int -> Predicate+isIntegerBetween low high (Token Numeral nd) =+  TNumeral.isIntegerBetween (TNumeral.value nd) low high+isIntegerBetween _ _ _ = False++isOrdinalBetween :: Int -> Int -> Predicate+isOrdinalBetween low high (Token Ordinal od) =+  TOrdinal.isBetween (TOrdinal.value od) low high+isOrdinalBetween _ _ _ = False++isDOMOrdinal :: Predicate+isDOMOrdinal = isOrdinalBetween 1 31++isDOMInteger :: Predicate+isDOMInteger = isIntegerBetween 1 31++isDOMValue :: Predicate+isDOMValue = liftM2 (||) isDOMOrdinal isDOMInteger++-- -----------------------------------------------------------------+-- Production++-- Pass the interval second+intersect :: TimeData -> TimeData -> Maybe TimeData+intersect td1 td2 =+  case intersect' (td1, td2) of+    TTime.TimeData { TTime.timePred = pred }+      | TTime.isEmptyPredicate pred -> Nothing+    res -> Just res++intersect' :: (TimeData, TimeData) -> TimeData+intersect' (TimeData pred1 _ g1 _ _ d1, TimeData pred2 _ g2 _ _ d2)+  | g1 < g2 = TTime.timedata'+    { TTime.timePred = timeCompose pred1 pred2+    , TTime.timeGrain = g1+    , TTime.direction = dir+    }+  | otherwise = TTime.timedata'+    { TTime.timePred = timeCompose pred2 pred1+    , TTime.timeGrain = g2+    , TTime.direction = dir+    }+  where+    dir = case catMaybes [d1, d2] of+      [] -> Nothing+      (x:_) -> Just x+++hour :: Bool -> Int -> TimeData+hour is12H n = timeOfDay (Just n) is12H $ TTime.timedata'+  {TTime.timePred = timeHour is12H n, TTime.timeGrain = TG.Hour}++minute :: Int -> TimeData+minute n = TTime.timedata'+  {TTime.timePred = timeMinute n, TTime.timeGrain = TG.Minute}++second :: Int -> TimeData+second n = TTime.timedata'+  {TTime.timePred = timeSecond n, TTime.timeGrain = TG.Second}++dayOfWeek :: Int -> TimeData+dayOfWeek n = form TTime.DayOfWeek $ TTime.timedata'+  { TTime.timePred = timeDayOfWeek n+  , TTime.timeGrain = TG.Day+  , TTime.notImmediate = True+  }++dayOfMonth :: Int -> TimeData+dayOfMonth n = TTime.timedata'+  {TTime.timePred = timeDayOfMonth n, TTime.timeGrain = TG.Day}++month :: Int -> TimeData+month n = form TTime.Month {TTime.month = n} $ TTime.timedata'+  {TTime.timePred = timeMonth n, TTime.timeGrain = TG.Month}++year :: Int -> TimeData+year n = TTime.timedata' {TTime.timePred = timeYear n, TTime.timeGrain = TG.Year}++yearMonthDay :: Int -> Int -> Int -> TimeData+yearMonthDay y m d = intersect' (intersect' (year y, month m), dayOfMonth d)++monthDay :: Int -> Int -> TimeData+monthDay m d = intersect' (month m, dayOfMonth d)++hourMinute :: Bool -> Int -> Int -> TimeData+hourMinute is12H h m = timeOfDay (Just h) is12H $+  intersect' (hour is12H h, minute m)++hourMinuteSecond :: Bool -> Int -> Int -> Int -> TimeData+hourMinuteSecond is12H h m s = timeOfDay (Just h) is12H $+  intersect' (intersect' (hour is12H h, minute m), second s)++cycleN :: Bool -> TG.Grain -> Int -> TimeData+cycleN notImmediate grain n = TTime.timedata'+  { TTime.timePred = takeN n notImmediate $ timeCycle grain+  , TTime.timeGrain = grain+  }++cycleNth :: TG.Grain -> Int -> TimeData+cycleNth grain n = TTime.timedata'+  {TTime.timePred = takeNth n False $ timeCycle grain, TTime.timeGrain = grain}++cycleNthAfter :: Bool -> TG.Grain -> Int -> TimeData -> TimeData+cycleNthAfter notImmediate grain n TimeData {TTime.timePred = p} =+  TTime.timedata'+    { TTime.timePred = takeNthAfter n notImmediate (timeCycle grain) p+    , TTime.timeGrain = grain+    }++cycleLastOf :: TG.Grain -> TimeData -> TimeData+cycleLastOf grain TimeData {TTime.timePred = p} = TTime.timedata'+  { TTime.timePred = takeLastOf (timeCycle grain) p+  , TTime.timeGrain = grain+  }++-- Generalized version of cycleLastOf with custom predicate+predLastOf :: TimeData -> TimeData -> TimeData+predLastOf TimeData {TTime.timePred = cyclicPred, TTime.timeGrain = g} base =+  TTime.timedata'+    { TTime.timePred = takeLastOf cyclicPred $ TTime.timePred base+    , TTime.timeGrain = g+    }++-- Generalized version of cycleNth with custom predicate+predNth :: Int -> Bool -> TimeData -> TimeData+predNth n notImmediate TimeData {TTime.timePred = p, TTime.timeGrain = g} =+  TTime.timedata'+    {TTime.timePred = takeNth n notImmediate p, TTime.timeGrain = g}++-- Generalized version of `cycleNthAfter` with custom predicate+predNthAfter :: Int -> TimeData -> TimeData -> TimeData+predNthAfter n TimeData {TTime.timePred = p, TTime.timeGrain = g} base =+  TTime.timedata'+    { TTime.timePred = takeNthAfter n True p $ TTime.timePred base+    , TTime.timeGrain = g+    }++interval :: TTime.TimeIntervalType -> (TimeData, TimeData) -> TimeData+interval intervalType (TimeData p1 _ g1 _ _ _, TimeData p2 _ g2 _ _ _) =+  TTime.timedata'+    { TTime.timePred = mkTimeIntervalsPredicate intervalType' p1 p2+    , TTime.timeGrain = min g1 g2+    }+    where+      intervalType'+        | g1 == g2 && g1 == TG.Day = TTime.Closed+        | otherwise = intervalType++durationAgo :: DurationData -> TimeData+durationAgo dd = inDuration $ timeNegPeriod dd++durationAfter :: DurationData -> TimeData -> TimeData+durationAfter dd TimeData {TTime.timePred = pred1} = TTime.timedata'+  { TTime.timePred = shiftDuration pred1 dd+  , TTime.timeGrain = TDuration.grain dd}++durationBefore :: DurationData -> TimeData -> TimeData+durationBefore dd pred1 = durationAfter (timeNegPeriod dd) pred1++inDuration :: DurationData -> TimeData+inDuration dd = TTime.timedata'+  { TTime.timePred = shiftDuration (takeNth 0 False $ timeCycle TG.Second) dd+  , TTime.timeGrain = TDuration.grain dd+  }++inTimezone :: Text -> TimeData -> Maybe TimeData+inTimezone input td@TimeData {TTime.timePred = p} = do+  tz <- parseTimezone input+  Just $ td {TTime.timePred = shiftTimezone (Series.TimeZoneSeries tz []) p}++mkLatent :: TimeData -> TimeData+mkLatent td = td {TTime.latent = True}++notLatent :: TimeData -> TimeData+notLatent td = td {TTime.latent = False}++form :: TTime.Form -> TimeData -> TimeData+form f td = td {TTime.form = Just f}++partOfDay :: TimeData -> TimeData+partOfDay td = form TTime.PartOfDay td++timeOfDay :: Maybe Int -> Bool -> TimeData -> TimeData+timeOfDay h is12H = form TTime.TimeOfDay {TTime.hours = h, TTime.is12H = is12H}++timeOfDayAMPM :: TimeData -> Bool -> TimeData+timeOfDayAMPM tod isAM = timeOfDay Nothing False $ intersect' (tod, ampm)+  where+    ampm = TTime.timedata'+           { TTime.timePred = ampmPred+           , TTime.timeGrain = TG.Hour+           }+    ampmPred = if isAM then mkAMPMPredicate AM else mkAMPMPredicate PM++withDirection :: TTime.IntervalDirection -> TimeData -> TimeData+withDirection dir td = td {TTime.direction = Just dir}++longWEBefore :: TimeData -> TimeData+longWEBefore monday = interval TTime.Open (start, end)+  where+    start = intersect' (fri, hour False 18)+    end = intersect' (tue, hour False 0)+    fri = cycleNthAfter False TG.Day (- 3) monday+    tue = cycleNthAfter False TG.Day 1 monday++daysOfWeekOfMonth :: Int -> Int -> TimeData+daysOfWeekOfMonth dow m = intersect' (dayOfWeek dow, month m)++-- Zero-indexed weeks, Monday is 1+-- Use `predLastOf` for last day of week of month+nthDOWOfMonth :: Int -> Int -> Int -> TimeData+nthDOWOfMonth n dow m = intersect' (dowsM, week)+  where+    dowsM = daysOfWeekOfMonth dow m+    week = cycleNthAfter False TG.Week n $ monthDay m 1++intersectDOM :: TimeData -> Token -> Maybe TimeData+intersectDOM td token = do+  n <- getIntValue token+  intersect (dayOfMonth n) td++minutesBefore :: Int -> TimeData -> Maybe TimeData+minutesBefore n TimeData {TTime.form = Just (TTime.TimeOfDay (Just 0) is12H)} =+  Just $ hourMinute is12H 23 (60 - n)+minutesBefore n TimeData {TTime.form = Just (TTime.TimeOfDay (Just 1) True)} =+  Just $ hourMinute True 12 (60 - n)+minutesBefore n TimeData {TTime.form = Just (TTime.TimeOfDay (Just h) is12H)} =+  Just $ hourMinute is12H (h - 1) (60 - n)+minutesBefore _ _ = Nothing++minutesAfter :: Int -> TimeData -> Maybe TimeData+minutesAfter n TimeData {TTime.form = Just (TTime.TimeOfDay (Just h) is12H)} =+  Just $ hourMinute is12H h n+minutesAfter _ _ = Nothing++-- | Convenience helper to return a time token from a rule+tt :: TimeData -> Maybe Token+tt = Just . Token Time
+ Duckling/Time/IT/Corpus.hs view
@@ -0,0 +1,814 @@+-- 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.Time.IT.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = IT}, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext {lang = IT}, examples)+  where+    examples =+      [ "ma"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "subito"+             , "immediatamente"+             , "in questo momento"+             , "ora"+             , "adesso"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "di oggi"+             , "oggi"+             , "in giornata"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "ieri"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "domani"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "Il giorno dopo domani"+             , "dopodomani"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Lunedì 18 febbraio"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "martedì"+             , "Martedì 19"+             , "mar 19"+             , "il 19"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "l'altro ieri"+             , "altroieri"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lunedi"+             , "lun"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "lunedi 18 febbraio"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "Martedì"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Mercoledì"+             , "mer"+             , "mer."+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercoledi 13 feb"+             , "il 13 febbraio"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "il 13 febbraio 2013"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "giovedi"+             , "gio"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "venerdi"+             , "venerdì"+             , "ven"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "sabato"+             , "sab"+             , "sab."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "domenica"+             , "dom"+             , "dom."+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "domenica 10 febbraio"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "il 1 marzo"+             , "primo marzo"+             , "primo di marzo"+             , "il 1º marzo"+             ]+  , examples (datetimeOpenInterval Before (2013, 3, 1, 0, 0, 0) Month)+             [ "prima di marzo"+             ]+  , examples (datetime (2013, 3, 15, 0, 0, 0) Day)+             [ "le idi di marzo"+             , "idi di marzo"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3 marzo 2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "il 15 febbraio"+             , "15/2"+             , "il 15/02"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "martedì scorso"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "martedì prossimo"+             , "il martedì dopo"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "mercoledì prossimo"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "ottobre 2014"+             ]+  , examples (datetime (2013, 2, 12, 3, 0, 0) Hour)+             [ "l'ultima ora"+             , "nell'ultima ora"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "questa settimana"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "la settimana scorsa"+             , "la scorsa settimana"+             , "nella scorsa settimana"+             , "della settimana scorsa"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "la settimana prossima"+             , "la prossima settimana"+             , "nella prossima settimana"+             , "settimana prossima"+             , "prossima settimana"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "il mese scorso"+             , "nel mese scorso"+             , "nel mese passato"+             , "lo scorso mese"+             , "dello scorso mese"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "il mese prossimo"+             , "il prossimo mese"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "questo trimestre"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "il prossimo trimestre"+             , "nel prossimo trimestre"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "terzo trimestre"+             , "il terzo trimestre"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "quarto trimestre 2018"+             , "il quarto trimestre 2018"+             , "del quarto trimestre 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "l'anno scorso"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "quest'anno"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "il prossimo anno"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "ultima domenica"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "lunedì di questa settimana"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "martedì di questa settimana"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "mercoledì di questa settimana"+             ]+  , examples (datetime (2013, 2, 14, 17, 0, 0) Hour)+             [ "dopo domani alle 17"+             , "dopodomani alle 5 del pomeriggio"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "ultimo lunedì di marzo"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "ultima domenica di marzo 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "il terzo giorno di ottobre"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "prima settimana di ottobre 2014"+             ]+  , examples (datetime (2013, 10, 7, 0, 0, 0) Week)+             [ "la settimana del 6 ottobre"+             , "la settimana del 7 ott"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "il we del 15 febbraio"+             ]+  , examples (datetimeInterval ((2013, 4, 12, 18, 0, 0), (2013, 4, 15, 0, 0, 0)) Hour)+             [ "il week-end del 10 aprile"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "l'ultimo giorno di ottobre 2015"+             , "l'ultimo giorno dell'ottobre 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "l'ultima settimana di settembre 2014"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "tra un'ora"+             , "tra 1 ora"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "tra un quarto d'ora"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "tra mezz'ora"+             ]+  , examples (datetime (2013, 2, 12, 5, 15, 0) Second)+             [ "tra tre quarti d'ora"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "primo martedì di ottobre"+             , "primo martedì in ottobre"+             , "1° martedì del mese di ottobre"+             , "1º martedì del mese di ottobre"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "terzo martedì di settembre 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "primo mercoledì di ottobre 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "secondo mercoledì di ottobre 2014"+             ]+  , examples (datetime (2015, 1, 13, 0, 0, 0) Day)+             [ "terzo martedì dopo natale 2014"+             ]+  , examples (datetime (2016, 1, 0, 0, 0, 0) Month)+             [ "il mese dopo natale 2015"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "alle 3 di pomeriggio"+             , "le tre di pomeriggio"+             , "alle 3 del pomeriggio"+             , "le tre del pomeriggio"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "circa alle 3 del pomeriggio"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "per le 15"+             , "verso le 15"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Minute)+             [ "3:00"+             , "03:00"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "3:15 di pomeriggio"+             , "3:15 del pomeriggio"+             , "3 e un quarto di pomeriggio"+             , "tre e un quarto di pomeriggio"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "alle tre e venti di pomeriggio"+             , "alle tre e venti del pomeriggio"+             , "3:20 di pomeriggio"+             , "3:20 del pomeriggio"+             , "15:20 del pomeriggio"+             ]+  , examples (datetime (2013, 2, 13, 3, 20, 0) Minute)+             [ "alle tre e venti"+             , "tre e 20"+             , "3 e 20"+             , "3:20"+             , "3 20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "15:30"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "a mezzogiorno meno un quarto"+             , "mezzogiorno meno un quarto"+             , "un quarto a mezzogiorno"+             , "11:45 del mattino"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "alle 3 del mattino"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "alle 19:30 di venerdì 20 settembre"+             , "alle 19:30 venerdì 20 settembre"+             , "venerdì 20 settembre alle 19:30"+             , "il 20 settembre alle 19:30"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "questo week-end"+             , "questo fine settimana"+             , "questo finesettimana"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "lunedi mattina"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "15 febbraio al mattino"+             , "mattino di 15 febbraio"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 di stasera"+             , "8 della sera"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "venerdì 20 settembre alle 7:30 del pomeriggio"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "alle 9 di sabato"+             , "sabato alle 9"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "quest'estate"+             , "questa estate"+             , "in estate"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "quest'inverno"+             , "questo inverno"+             , "in inverno"+             ]+  , examples (datetimeInterval ((2014, 9, 23, 0, 0, 0), (2014, 12, 22, 0, 0, 0)) Day)+             [ "il prossimo autunno"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "natale"+             , "il giorno di natale"+             ]+  , examples (datetime (2013, 12, 24, 0, 0, 0) Day)+             [ "vigilia di natale"+             , "alla vigilia"+             , "la vigilia"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "vigilia di capodanno"+             , "san silvestro"+             ]+  , examples (datetimeInterval ((2014, 1, 1, 0, 0, 0), (2014, 1, 1, 4, 0, 0)) Hour)+             [ "notte di san silvestro"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "capodanno"+             , "primo dell'anno"+             ]+  , examples (datetime (2014, 1, 6, 0, 0, 0) Day)+             [ "epifania"+             , "befana"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "san valentino"+             , "festa degli innamorati"+             ]+  , examples (datetime (2013, 3, 19, 0, 0, 0) Day)+             [ "festa del papà"+             , "festa del papa"+             , "festa di san giuseppe"+             , "san giuseppe"+             ]+  , examples (datetime (2013, 4, 25, 0, 0, 0) Day)+             [ "anniversario della liberazione"+             , "la liberazione"+             , "alla liberazione"+             ]+  , examples (datetime (2013, 5, 1, 0, 0, 0) Day)+             [ "festa del lavoro"+             , "festa dei lavoratori"+             , "giorno dei lavoratori"+             , "primo maggio"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "festa della mamma"+             ]+  , examples (datetime (2013, 6, 2, 0, 0, 0) Day)+             [ "festa della repubblica"+             , "la repubblica"+             , "repubblica"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "ferragosto"+             , "assunzione"+             ]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "halloween"+             ]+  , examples (datetime (2013, 11, 1, 0, 0, 0) Day)+             [ "tutti i santi"+             , "ognissanti"+             , "festa dei santi"+             , "il giorno dei santi"+             ]+  , examples (datetime (2013, 11, 2, 0, 0, 0) Day)+             [ "giorno dei morti"+             , "commemorazione dei defunti"+             ]+  , examples (datetime (2013, 11, 2, 2, 0, 0) Hour)+             [ "ai morti alle 2"+             ]+  , examples (datetime (2013, 12, 8, 0, 0, 0) Day)+             [ "immacolata"+             , "immacolata concezione"+             , "all'immacolata"+             ]+  , examples (datetime (2013, 12, 8, 18, 0, 0) Hour)+             [ "all'immacolata alle 18"+             ]+  , examples (datetime (2013, 12, 26, 0, 0, 0) Day)+             [ "santo stefano"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "questa sera"+             , "sta sera"+             , "stasera"+             , "in serata"+             , "nella sera"+             , "verso sera"+             , "la sera"+             , "alla sera"+             , "la serata"+             , "nella serata"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 4, 0, 0), (2013, 2, 13, 12, 0, 0)) Hour)+             [ "domani mattina"+             , "domattina"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 18, 0, 0, 0)) Second)+             [ "in settimana"+             , "per la settimana"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 13, 4, 0, 0)) Hour)+             [ "stanotte"+             , "nella notte"+             , "in nottata"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "ultimo weekend"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "domani in serata"+             , "domani sera"+             , "nella serata di domani"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 0, 0, 0), (2013, 2, 14, 4, 0, 0)) Hour)+             [ "domani notte"+             , "domani in nottata"+             , "nella nottata di domani"+             , "nella notte di domani"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "domani a pranzo"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "ieri sera"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "questo weekend"+             , "questo week-end"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "lunedì mattina"+             , "nella mattinata di lunedì"+             , "lunedì in mattinata"+             , "lunedì nella mattina"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "il 15 febbraio in mattinata"+             , "mattina del 15 febbraio"+             , "15 febbraio mattina"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "gli ultimi 2 secondi"+             , "gli ultimi due secondi"+             , "i 2 secondi passati"+             , "i due secondi passati"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "i prossimi 3 secondi"+             , "i prossimi tre secondi"+             , "nei prossimi tre secondi"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "gli ultimi 2 minuti"+             , "gli ultimi due minuti"+             , "i 2 minuti passati"+             , "i due minuti passati"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "i prossimi 3 minuti"+             , "nei prossimi 3 minuti"+             , "i prossimi tre minuti"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 2, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "le ultime 2 ore"+             , "le ultime due ore"+             , "nelle ultime due ore"+             , "le scorse due ore"+             , "le due ore scorse"+             , "le scorse 2 ore"+             , "le 2 ore scorse"+             , "nelle 2 ore scorse"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 4, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "le ultime 24 ore"+             , "le ultime ventiquattro ore"+             , "le 24 ore passate"+             , "nelle 24 ore scorse"+             , "le ventiquattro ore passate"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "le prossime 3 ore"+             , "prossime tre ore"+             , "nelle prossime 3 ore"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "gli ultimi 2 giorni"+             , "gli ultimi due giorni"+             , "negli ultimi 2 giorni"+             , "i 2 giorni passati"+             , "i due giorni passati"+             , "nei due giorni passati"+             , "gli scorsi due giorni"+             , "i 2 giorni scorsi"+             , "i due giorni scorsi"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "prossimi 3 giorni"+             , "i prossimi tre giorni"+             , "nei prossimi 3 giorni"+             , "prossimi giorni"+             , "nei prossimi giorni"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "le ultime 2 settimane"+             , "le ultime due settimane"+             , "le 2 ultime settimane"+             , "le due ultime settimane"+             , "nelle 2 ultime settimane"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "prossime 3 settimane"+             , "le prossime tre settimane"+             , "le 3 prossime settimane"+             , "nelle prossime 3 settimane"+             , "le tre prossime settimane"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "gli ultimi 2 mesi"+             , "gli ultimi due mesi"+             , "i 2 mesi passati"+             , "nei 2 mesi passati"+             , "i due mesi passati"+             , "i due mesi scorsi"+             , "i 2 mesi scorsi"+             , "negli scorsi due mesi"+             , "gli scorsi due mesi"+             , "gli scorsi 2 mesi"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "i prossimi 3 mesi"+             , "i prossimi tre mesi"+             , "prossimi 3 mesi"+             , "i 3 prossimi mesi"+             , "i tre prossimi mesi"+             , "nei prossimi tre mesi"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "gli ultimi 2 anni"+             , "gli ultimi due anni"+             , "negli ultimi 2 anni"+             , "i 2 anni passati"+             , "i due anni passati"+             , "i 2 anni scorsi"+             , "i due anni scorsi"+             , "gli scorsi due anni"+             , "gli scorsi 2 anni"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "i prossimi 3 anni"+             , "i prossimi tre anni"+             , "nei tre prossimi anni"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13-15 luglio"+             , "dal 13 al 15 luglio"+             , "tra il 13 e il 15 luglio"+             , "tra 13 e 15 luglio"+             , "dal tredici al quindici luglio"+             , "13 luglio - 15 luglio"+             ]+  , examples (datetimeInterval ((2013, 3, 3, 0, 0, 0), (2013, 3, 6, 0, 0, 0)) Day)+             [ "dal 3 al 5"+             , "tra il 3 e il 5"+             , "dal tre al cinque"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "8 ago - 12 ago"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 15, 0, 0, 0)) Day)+             [ "da domani a giovedì"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "dalle 9:30 alle 11:00 di giovedì"+             , "tra le 9:30 e le 11:00 di giovedì"+             , "9:30 - 11:00 giovedì"+             , "giovedì dalle 9:30 alle 11:00"+             , "giovedì tra le 9:30 e le 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "dalle 9 alle 11 di giovedì"+             , "tra le 9 e le 11 di giovedì"+             , "9 - 11 giovedì"+             , "giovedì dalle nove alle undici"+             , "giovedì tra le nove e le undici"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 3, 0, 0), (2013, 2, 14, 14, 0, 0)) Hour)+             [ "dalle tre all'una di giovedì"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 13, 3, 0, 0)) Hour)+             [ "dalla mezzanotte alle 2"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 15, 0, 0), (2013, 2, 13, 17, 1, 0)) Minute)+             [ "domani dalle 15:00 alle 17:00"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-13:30"+             ]+  , examples (datetime (2013, 9, 21, 13, 30, 0) Minute)+             [ "13:30 di sabato 21 settembre"+             , "13:30 del 21 settembre"+             ]+  , examples (datetime (2013, 2, 26, 0, 0, 0) Day)+             [ "in due settimane"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 12, 14, 0, 0)) Second)+             [ "fino alle 14:00"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Minute)+             [ "entro le 14:00"+             ]+  , examples (datetimeOpenInterval Before (2013, 3, 1, 0, 0, 0) Month)+             [ "entro la fine del mese"+             ]+  , examples (datetimeOpenInterval Before (2014, 1, 1, 0, 0, 0) Year)+             [ "entro la fine dell'anno"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 3, 1, 0, 0, 0)) Second)+             [ "fino alla fine del mese"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2014, 1, 1, 0, 0, 0)) Second)+             [ "fino alla fine dell'anno"+             ]+  , examples (datetime (2013, 2, 13, 1, 0, 0) Minute)+             [ "alle 4 CET"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "alle 16 CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "giovedì alle 8:00 GMT"+             ]+  , examples (datetime (2013, 2, 13, 14, 0, 0) Hour)+             [ "domani alle 14"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "alle 14"+             , "alle 2 del pomeriggio"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)+             [ "25/4 alle 16:00"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "3 del pomeriggio di domani"+             , "15 del pomeriggio di domani"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "dopo le 14"+             , "dalle 14"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 0, 0, 0) Hour)+             [ "dalla mezzanotte"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 14, 0, 0) Hour)+             [ "domani dopo le 14"+             , "domani dalle 14"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "prima delle 11"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 14, 11, 0, 0) Hour)+             [ "dopodomani prima delle 11"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 14, 12, 0, 0) Hour)+             [ "giovedì entro mezzogiorno"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 14, 0, 0, 0) Day)+             [ "da dopodomani"+             , "da giovedì"+             ]+  , examples (datetimeOpenInterval After (2013, 3, 1, 0, 0, 0) Day)+             [ "dal primo"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 20, 0, 0, 0) Day)+             [ "dal 20"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 15, 0, 0, 0) Day)+             [ "entro il 15"+             ]+  , examples (datetimeOpenInterval Before (2013, 4, 20, 0, 0, 0) Day)+             [ "prima del 20 aprile"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "nel pomeriggio"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "alle 13:30"+             , "13:30"+             , "1:30 del pomeriggio"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "in 15 minuti"+             , "tra 15 minuti"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "questa mattina"+             , "questa mattinata"+             , "questo mattino"+             ]+  , examples (datetime (2013, 2, 25, 0, 0, 0) Day)+             [ "prossimo lunedì"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "alle 12"+             , "a mezzogiorno"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "alle 24"+             , "a mezzanotte"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             [ "marzo"+             , "in marzo"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "gio 15"+             ]+  ]
+ Duckling/Time/IT/Rules.hs view
@@ -0,0 +1,2569 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.IT.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Types (NumeralData(..))+import qualified Duckling.Numeral.Types as TNumeral+import Duckling.Ordinal.Types (OrdinalData(..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleFestaDellaRepubblica :: Rule+ruleFestaDellaRepubblica = Rule+  { name = "festa della repubblica"+  , pattern =+    [ regex "((festa del)?la )?repubblica"+    ]+  , prod = \_ -> tt $ monthDay 6 2+  }++ruleEpifania :: Rule+ruleEpifania = Rule+  { name = "epifania"+  , pattern =+    [ regex "(epifania|befana)"+    ]+  , prod = \_ -> tt $ monthDay 1 6+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "luned(i|\x00ec)|lun?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleDayofmonthNamedmonth :: Rule+ruleDayofmonthNamedmonth = Rule+  { name = "<day-of-month> <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "(il giorno )?dopo\\s?domani"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleInafterDuration :: Rule+ruleInafterDuration = Rule+  { name = "in/after <duration>"+  , pattern =+    [ regex "[tf]ra|in|dopo"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleTheLastCycle :: Rule+ruleTheLastCycle = Rule+  { name = "the last <cycle>"+  , pattern =+    [ regex "(([nd]el)?l' ?ultim|(il|la) passat|([nd]el)?l[ao] scors)[oa]"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleStanotte :: Rule+ruleStanotte = Rule+  { name = "stanotte"+  , pattern =+    [ regex "(sta|nella )notte|(in|nella) nottata"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 1+          td2 = interval TTime.Open (hour False 0, hour False 4)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleDomattina :: Rule+ruleDomattina = Rule+  { name = "domattina"+  , pattern =+    [ regex "domattina"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 1+          td2 = interval TTime.Open (hour False 4, hour False 12)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "dicembre|dic\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleTheCycleNext :: Rule+ruleTheCycleNext = Rule+  { name = "the <cycle> next"+  , pattern =+    [ regex "l'|il|la|[nd]el(la)?"+    , dimension TimeGrain+    , regex "prossim[oa]"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleCycleNext :: Rule+ruleCycleNext = Rule+  { name = "<cycle> next"+  , pattern =+    [ dimension TimeGrain+    , regex "prossim[oa]"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleFestaDellaLiberazione :: Rule+ruleFestaDellaLiberazione = Rule+  { name = "festa della liberazione"+  , pattern =+    [ regex "((festa|anniversario) della|(al)?la) liberazione"+    ]+  , prod = \_ -> tt $ monthDay 4 25+  }++ruleStamattina :: Rule+ruleStamattina = Rule+  { name = "stamattina"+  , pattern =+    [ regex "stamattina"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 4, hour False 12)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "marted(i|\x00ec)|mar\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleYearNotLatent :: Rule+ruleYearNotLatent = Rule+  { name = "year (1000-2100 not latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "san valentino|festa degli innamorati"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleTheOrdinalCycleOfTime :: Rule+ruleTheOrdinalCycleOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "il|l[a']|[nd]el(l[a'])?"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "di|del(l[a'])?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleTheOrdinalQuarter :: Rule+ruleTheOrdinalQuarter = Rule+  { name = "the <ordinal> quarter"+  , pattern =+    [ regex "il|[nd]el(l')?|l'"+    , dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleCycleOrdinalQuarterYear :: Rule+ruleCycleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (n - 1) td+      _ -> Nothing+  }++ruleCycleTheOrdinalTime :: Rule+ruleCycleTheOrdinalTime = Rule+  { name = "the <ordinal> <cycle> <time>"+  , pattern =+    [ regex "il|[nd]el(l')?|l'"+    , dimension Ordinal+    , dimension TimeGrain+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter True grain (n - 1) td+      _ -> Nothing+  }++ruleDdddMonthInterval :: Rule+ruleDdddMonthInterval = Rule+  { name = "dd-dd <month> (interval)"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       Token Time td:+       _) -> do+         v1 <- parseInt m1+         v2 <- parseInt m2+         from <- intersect (dayOfMonth v1) td+         to <- intersect (dayOfMonth v2) td+         tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleTimeLast :: Rule+ruleTimeLast = Rule+  { name = "<time> last"+  , pattern =+    [ dimension Time+    , regex "(ultim|scors|passat)[oaie]"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleThisDayofweek :: Rule+ruleThisDayofweek = Rule+  { name = "this <day-of-week>"+  , pattern =+    [ regex "quest[oaie]"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleUna :: Rule+ruleUna = Rule+  { name = "una"+  , pattern =+    [ regex "una"+    ]+  , prod = \_ -> tt . mkLatent $ hour True 1+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "di|del(l[oa'])|in"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal OrdinalData {TOrdinal.value = v}:+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "(capodanno|primo dell' ?anno)"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time> "+  , pattern =+    [ regex "(ultim|scors|passat)[oaie]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleIlDayofmonthDeNamedmonth :: Rule+ruleIlDayofmonthDeNamedmonth = Rule+  { name = "il <day-of-month> <named-month>"+  , pattern =+    [ regex "il|l'"+    , Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sabato|sab\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|[fs]ino a(l(l[e'])?)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "luglio|lug\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "ser(ata|[ae])"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayOfMonthSt :: Rule+ruleDayOfMonthSt = Rule+  { name = "day of month (1st)"+  , pattern =+    [ regex "(primo|1o|1\x00ba|1\x00b0)"+    ]+  , prod = \_ -> tt $ dayOfMonth 1+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in|entro <duration>"+  , pattern =+    [ regex "(in|entro)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       Token Duration dd:+       _) -> case Text.toLower match of+        "entro" -> tt $+          interval TTime.Open (cycleNth TG.Second 0, inDuration dd)+        "in"    -> tt $ inDuration dd+        _       -> Nothing+      _ -> Nothing+  }++ruleInNamedmonth :: Rule+ruleInNamedmonth = Rule+  { name = "in <named-month>"+  , pattern =+    [ regex "in|del mese( di)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleLeIdiDiNamedmonth :: Rule+ruleLeIdiDiNamedmonth = Rule+  { name = "le idi di <named-month>"+  , pattern =+    [ regex "(le )?idi di"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td+      _ -> Nothing+  }++ruleRightNow :: Rule+ruleRightNow = Rule+  { name = "right now"+  , pattern =+    [ regex "(subito|(immediata|attual)mente|(proprio )?adesso|(in questo|al) momento|ora)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "(di )?oggi|in giornata"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "(l')ultim[oa]"+    , dimension TimeGrain+    , regex "di|del(l[oa'])"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleHhRelativeminutesDelPomeriggiotimeofday2 :: Rule+ruleHhRelativeminutesDelPomeriggiotimeofday2 = Rule+  { name = "hh <relative-minutes> del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        let h = if hours > 12 then hours else hours + 12+        tt $ hourMinute False h n+      _ -> Nothing+  }+ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleHourofdayAndRelativeMinutes :: Rule+ruleHourofdayAndRelativeMinutes = Rule+  { name = "<hour-of-day> and <relative minutes>"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleRelativeMinutesToIntegerAsHourofday :: Rule+ruleRelativeMinutesToIntegerAsHourofday = Rule+  { name = "relative minutes to <integer> (as hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "a"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }+ruleHourofdayMinusIntegerAsRelativeMinutes :: Rule+ruleHourofdayMinusIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> minus <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meno"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }+ruleHhRelativeminutesDelPomeriggiotimeofday :: Rule+ruleHhRelativeminutesDelPomeriggiotimeofday = Rule+  { name = "hh <relative-minutes> del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+        n <- getIntValue token+        let h = if hours > 12 then hours else hours + 12+        tt $ hourMinute False h n+      _ -> Nothing+  }++ruleHhIntegerminutesDelPomeriggiotimeofday2 :: Rule+ruleHhIntegerminutesDelPomeriggiotimeofday2 = Rule+  { name = "hh <relative-minutes> minutes del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        let h = if hours > 12 then hours else hours + 12+        tt $ hourMinute False h n+      _ -> Nothing+  }+ruleHourofdayIntegerMinutes :: Rule+ruleHourofdayIntegerMinutes = Rule+  { name = "<hour-of-day> <integer> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleHourofdayAndIntegerMinutes :: Rule+ruleHourofdayAndIntegerMinutes = Rule+  { name = "<hour-of-day> and <integer> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleMinutesToIntegerAsHourofday :: Rule+ruleMinutesToIntegerAsHourofday = Rule+  { name = "minutes to <integer> (as hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)? a"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }+ruleHourofdayMinusIntegerMinutes :: Rule+ruleHourofdayMinusIntegerMinutes = Rule+  { name = "<hour-of-day> minus <integer> minutes"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meno"+    , Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       _:+       token:+       _) -> do+         v <- getIntValue token+         Token Time <$> minutesBefore v td+      _ -> Nothing+  }+ruleHhIntegerminutesDelPomeriggiotimeofday :: Rule+ruleHhIntegerminutesDelPomeriggiotimeofday = Rule+  { name = "hh <integer> minutes del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "min(ut[oi]|\\.)? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+         v <- getIntValue token+         let h = if hours > 12 then hours else hours + 12+         tt $ hourMinute False h v+      _ -> Nothing+  }++ruleHhQuartDelPomeriggiotimeofday2 :: Rule+ruleHhQuartDelPomeriggiotimeofday2 = Rule+  { name = "hh quart del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e un quarto d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 15+      _ -> Nothing+  }+ruleHourofdayQuart :: Rule+ruleHourofdayQuart = Rule+  { name = "<hour-of-day> quart"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "un quarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }+ruleHourofdayAndAQuart :: Rule+ruleHourofdayAndAQuart = Rule+  { name = "<hour-of-day> and a quart"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e un quarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }+ruleQuartAsHourofday :: Rule+ruleQuartAsHourofday = Rule+  { name = "a quart to <integer> (as hour-of-day)"+  , pattern =+    [ regex "un quarto a"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }+ruleHourofdayMinusQuart :: Rule+ruleHourofdayMinusQuart = Rule+  { name = "<hour-of-day> minus quart"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meno un quarto"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }+ruleHhQuartDelPomeriggiotimeofday :: Rule+ruleHhQuartDelPomeriggiotimeofday = Rule+  { name = "hh quart del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "un quarto d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 15+      _ -> Nothing+  }++ruleHhHalfDelPomeriggiotimeofday2 :: Rule+ruleHhHalfDelPomeriggiotimeofday2 = Rule+  { name = "hh half del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e mezzo d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 30+      _ -> Nothing+  }+ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "mezzo"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }+ruleHourofdayAndHalf :: Rule+ruleHourofdayAndHalf = Rule+  { name = "<hour-of-day> and half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e mezzo"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }+ruleHalfToIntegerAsHourofday :: Rule+ruleHalfToIntegerAsHourofday = Rule+  { name = "half to <integer> (as hour-of-day)"+  , pattern =+    [ regex "mezzo a"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }+ruleHourofdayMinusHalf :: Rule+ruleHourofdayMinusHalf = Rule+  { name = "<hour-of-day> minus half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meno mezzo"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }+ruleHhHalfDelPomeriggiotimeofday :: Rule+ruleHhHalfDelPomeriggiotimeofday = Rule+  { name = "hh half del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "mezzo d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 30+      _ -> Nothing+  }++ruleHhThreeQuarterDelPomeriggiotimeofday2 :: Rule+ruleHhThreeQuarterDelPomeriggiotimeofday2 = Rule+  { name = "hh three quarters del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e (3|tre) quarti? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 45+      _ -> Nothing+  }+ruleHourofdayThreeQuarters :: Rule+ruleHourofdayThreeQuarters = Rule+  { name = "<hour-of-day> three quarters"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(3|tre) quarti?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 45+      _ -> Nothing+  }+ruleHourofdayAndThreeQuarter :: Rule+ruleHourofdayAndThreeQuarter = Rule+  { name = "<hour-of-day> and three quarters"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e (3|tre) quarti?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 45+      _ -> Nothing+  }+ruleThreeQuarterToIntegerAsHourofday :: Rule+ruleThreeQuarterToIntegerAsHourofday = Rule+  { name = "three quarter to <integer> (as hour-of-day)"+  , pattern =+    [ regex "(3|tre) quarti? a"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 45 td+      _ -> Nothing+  }+ruleHourofdayMinusThreeQuarter :: Rule+ruleHourofdayMinusThreeQuarter = Rule+  { name = "<hour-of-day> minus three quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meno (3|tre) quarti?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 45 td+      _ -> Nothing+  }+ruleHhThreeQuarterDelPomeriggiotimeofday :: Rule+ruleHhThreeQuarterDelPomeriggiotimeofday = Rule+  { name = "hh three quarter del pomeriggio(time-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(3|tre) quarti? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) ->+         let h = if hours > 12 then hours else hours + 12+         in tt $ hourMinute False h 45+      _ -> Nothing+  }++ruleHhhmmTimeofday :: Rule+ruleHhhmmTimeofday = Rule+  { name = "hh(:|h)mm (time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:h]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute False h m+      _ -> Nothing+  }++ruleDalIntAlInt :: Rule+ruleDalIntAlInt = Rule+  { name = "dal <integer> al <integer> (interval)"+  , pattern =+    [ regex "dal(?:l')?"+    , Predicate isDOMInteger+    , regex "([fs]ino )?al(l')?"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token1:_:token2:_) -> do+         v1 <- getIntValue token1+         v2 <- getIntValue token2+         tt $+           interval TTime.Closed (dayOfMonth v1, dayOfMonth v2)+      _ -> Nothing+  }++ruleTraIlIntEIlInt :: Rule+ruleTraIlIntEIlInt = Rule+  { name = "tra il <integer> e il <integer> (interval)"+  , pattern =+    [ regex "tra( (il|l'))?"+    , Predicate isDOMInteger+    , regex "e( (il|l'))?"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token1:_:token2:_) -> do+         v1 <- getIntValue token1+         v2 <- getIntValue token2+         tt $+           interval TTime.Closed (dayOfMonth v1, dayOfMonth v2)+      _ -> Nothing+  }++ruleTimeofdayOra :: Rule+ruleTimeofdayOra = Rule+  { name = "<time-of-day> ora"+  , pattern =+    [ regex "or[ea]"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNextTime2 :: Rule+ruleNextTime2 = Rule+  { name = "next <time>"+  , pattern =+    [ dimension Time+    , regex "dopo|prossim[ao]"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "gioved(i|\x00ec)|gio\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleSantoStefano :: Rule+ruleSantoStefano = Rule+  { name = "santo stefano"+  , pattern =+    [ regex "s(anto|\\.) stefano"+    ]+  , prod = \_ -> tt $ monthDay 12 26+  }++ruleIlTime :: Rule+ruleIlTime = Rule+  { name = "il <time>"+  , pattern =+    [ regex "il|l'"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleFestaDelPap :: Rule+ruleFestaDelPap = Rule+  { name = "festa del papà"+  , pattern =+    [ regex "festa del pap(a|\x00e0)|(festa di )?s(an|\\.) giuseppe"+    ]+  , prod = \_ -> tt $ monthDay 3 19+  }++ruleEntroIlDuration :: Rule+ruleEntroIlDuration = Rule+  { name = "entro il <duration>"+  , pattern =+    [ regex "(entro|durante|per( tutt[ao])?) (il|l[a'])|in|nel(l[a'])?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        let from = cycleNth TG.Second 0+            to = cycleNth grain 1+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleDimTimeAlPartofday :: Rule+ruleDimTimeAlPartofday = Rule+  { name = "<dim time> al <part-of-day>"+  , pattern =+    [ dimension Time+    , regex "al|nel(la)?|in|d(i|el(la)?)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "(in )?primavera"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "mezz?ogiorno"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "(l')?altro\\s?ieri"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle> "+  , pattern =+    [ regex "((il|la|[nd]el(la)?) )?prossim[oa]"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "gennaio|genn?\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTheCycleOfTime :: Rule+ruleTheCycleOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ regex "il|la"+    , dimension TimeGrain+    , regex "del"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "marzo|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(a )?pranzo"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd[/-]mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[/-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        d <- parseInt m1+        m <- parseInt m2+        tt $ monthDay m d+      _ -> Nothing+  }++ruleGliUltimiNCycle :: Rule+ruleGliUltimiNCycle = Rule+  { name = "gli ultimi <n> <cycle>"+  , pattern =+    [ regex "((([nd]el)?le|([nd]e)?gli) )?(scors|ultim)[ei]"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "pomeriggio?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "aprile|apr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++rulePartofdayOfDimTime :: Rule+rulePartofdayOfDimTime = Rule+  { name = "<part-of-day> of <dim time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "d(i|el)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleDimTimeDelMattino :: Rule+ruleDimTimeDelMattino = Rule+  { name = "<dim time> del mattino"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "del mattino"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let from = hour False 0+            to = hour False 12+            td2 = mkLatent . partOfDay $ interval TTime.Open (from, to)+        in Token Time <$> intersect td td2+      _ -> Nothing+  }++ruleMidnight :: Rule+ruleMidnight = Rule+  { name = "midnight"+  , pattern =+    [ regex "mez?zanott?e"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "((al)?la )?vigig?lia( di natale)?"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "venerd(i|\x00ec)|ven\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "dopo"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleHhhmmTimeofday2 :: Rule+ruleHhhmmTimeofday2 = Rule+  { name = "hh(:|h)mm (time-of-day)"+  , pattern =+    [ regex "((?:0?\\d)|(?:1[0-2]))[:h]([0-5]\\d) d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        v1 <- parseInt m1+        v2 <- parseInt m2+        tt $ hourMinute False (v1 + 12) v2+      _ -> Nothing+  }++ruleTimeNotte :: Rule+ruleTimeNotte = Rule+  { name = "<time> notte"+  , pattern =+    [ dimension Time+    , regex "((in|nella|alla) )?nott(e|ata)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let td1 = cycleNthAfter False TG.Day 1 td+            td2 = interval TTime.Open (hour False 0, hour False 4)+        in Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "febbraio|febb?\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleStasera :: Rule+ruleStasera = Rule+  { name = "stasera"+  , pattern =+    [ regex "stasera"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "(in )?inverno"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "(in )?estate"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+       in tt $ interval TTime.Open (from, to)+  }++ruleIntegerLatentTimeofday :: Rule+ruleIntegerLatentTimeofday = Rule+  { name = "<integer> (latent time-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 24+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour False v+      _ -> Nothing+  }++ruleInThePartofdayOfDimTime :: Rule+ruleInThePartofdayOfDimTime = Rule+  { name = "in the <part-of-day> of <dim time>"+  , pattern =+    [ regex "nel(la)?"+    , Predicate isAPartOfDay+    , regex "d(i|el)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "((la )?vigig?lia di capodanno|san silvestro)"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleFerragosto :: Rule+ruleFerragosto = Rule+  { name = "ferragosto"+  , pattern =+    [ regex "ferragosto|assunzione"+    ]+  , prod = \_ -> tt $ monthDay 8 15+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "fa"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleTimeNotte2 :: Rule+ruleTimeNotte2 = Rule+  { name = "<time> notte"+  , pattern =+    [ regex "((nella|alla) )?nott(e|ata)( d(i|el))"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        let td1 = cycleNthAfter False TG.Day 1 td+            td2 = interval TTime.Open (hour False 0, hour False 4)+        in Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTimeofdayPrecise :: Rule+ruleTimeofdayPrecise = Rule+  { name = "<time-of-day> precise"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "precise"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleHhmmMilitaryTimeofday :: Rule+ruleHhmmMilitaryTimeofday = Rule+  { name = "hhmm (military time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt . mkLatent $ hourMinute False h m+      _ -> Nothing+  }++ruleTheCycleLast :: Rule+ruleTheCycleLast = Rule+  { name = "the <cycle> last"+  , pattern =+    [ regex "l'|il|la|[nd]el(la)?"+    , dimension TimeGrain+    , regex "(scors|passat)[oa]"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleFinoAlDatetimeInterval :: Rule+ruleFinoAlDatetimeInterval = Rule+  { name = "fino al <datetime> (interval)"+  , pattern =+    [ regex "[fs]ino a(l(l[ae'])?)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        let now = cycleNth TG.Second 0+        in tt $ interval TTime.Open (now, td)+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "(al)?l[e']|a"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleTheNthTimeOfTime :: Rule+ruleTheNthTimeOfTime = Rule+  { name = "the nth <time> of <time>"+  , pattern =+    [ regex "il|l[a']|[nd]el(l[a'])?"+    , dimension Ordinal+    , dimension Time+    , regex "di|del(l[a'])?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+         predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "giugno|giu\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "di|del(l[a'])?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+         predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "agosto|ago\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleDalDatetimeAlDatetimeInterval :: Rule+ruleDalDatetimeAlDatetimeInterval = Rule+  { name = "dal <datetime> al <datetime> (interval)"+  , pattern =+    [ regex "da(l(l')?)?"+    , Predicate isNotLatent+    , regex "([fs]ino )?a(l(l')?)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleTimeofdayTimeofdayDayofmonthInterval :: Rule+ruleTimeofdayTimeofdayDayofmonthInterval = Rule+  { name = "<time-of-day> - <time-of-day> <day-of-month> (interval)"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\\-"+    , Predicate isATimeOfDay+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:Token Time td3:_) -> do+        from <- intersect td1 td3+        to <- intersect td2 td3+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "week[ -]?end|fine ?settimana|we"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleIlWeekendDelTime :: Rule+ruleIlWeekendDelTime = Rule+  { name = "il week-end del <time>"+  , pattern =+    [ regex "il (week[ -]?end|fine ?settimana|we) del"+    , Predicate $ isGrainOfTime TG.Day+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> do+        from1 <- intersect (cycleNthAfter False TG.Week 0 td) (dayOfWeek 5)+        from <- intersect from1 (hour False 18)+        to1 <- intersect (cycleNthAfter False TG.Week 1 td) (dayOfWeek 1)+        to <- intersect to1 (hour False 0)+        tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "fine del mese"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleCommemorazioneDeiDefunti :: Rule+ruleCommemorazioneDeiDefunti = Rule+  { name = "commemorazione dei defunti"+  , pattern =+    [ regex "(((giorno|commemorazione) dei|ai) )?(morti|defunti)"+    ]+  , prod = \_ -> tt $ monthDay 11 2+  }++ruleImmacolataConcezione :: Rule+ruleImmacolataConcezione = Rule+  { name = "immacolata concezione"+  , pattern =+    [ regex "(all')?immacolata( concezione)?"+    ]+  , prod = \_ -> tt $ monthDay 12 8+  }++ruleDimTimePartofday :: Rule+ruleDimTimePartofday = Rule+  { name = "<dim time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTraIlDatetimeEIlDatetimeInterval :: Rule+ruleTraIlDatetimeEIlDatetimeInterval = Rule+  { name = "tra il <datetime> e il <datetime> (interval)"+  , pattern =+    [ regex "tra( il| l')?"+    , Predicate isATimeOfDay+    , regex "e( il| l')?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNthTimeAfterTime2 :: Rule+ruleNthTimeAfterTime2 = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ regex "il|l'"+    , dimension Ordinal+    , dimension Time+    , regex "dopo"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleDopoLeTimeofday :: Rule+ruleDopoLeTimeofday = Rule+  { name = "dopo le <time-of-day>"+  , pattern =+    [ regex "dopo( l['ea'])?|dal(l['ea'])?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt . withDirection TTime.After $ notLatent td+      _ -> Nothing+  }++ruleDopoTime :: Rule+ruleDopoTime = Rule+  { name = "dopo <time>"+  , pattern =+    [ regex "dopo|dal?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleDalInt :: Rule+ruleDalInt = Rule+  { name = "dal <integer"+  , pattern =+    [ regex "dal"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . withDirection TTime.After $ dayOfMonth v+      _ -> Nothing+  }++ruleTimeEntroLeTime :: Rule+ruleTimeEntroLeTime = Rule+  { name = "<time> entro le <time>"+  , pattern =+    [ dimension Time+    , regex "entro( l[e'])?|prima d(i|ell['ea])"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time . withDirection TTime.Before <$> intersect td1 td2+      _ -> Nothing+  }++ruleEntroTime :: Rule+ruleEntroTime = Rule+  { name = "entro <time>"+  , pattern =+    [ regex "entro( la)?|prima d(i|ella)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleEntroIlInt :: Rule+ruleEntroIlInt = Rule+  { name = "entro il <integer>"+  , pattern =+    [ regex "entro il|prima del"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . withDirection TTime.Before $ dayOfMonth v+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "prossim[ao]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleNthTimeOfTime3 :: Rule+ruleNthTimeOfTime3 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ regex "il|l'"+    , dimension Ordinal+    , dimension Time+    , regex "di|del(l[oa'])|in"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+         predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleIlCycleDopoTime :: Rule+ruleIlCycleDopoTime = Rule+  { name = "il <cycle> dopo <time>"+  , pattern =+    [ regex "l[a']|il|[nd]el"+    , dimension TimeGrain+    , regex "dopo"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "((([nd]e)?i|([nd]el)?le) )?prossim[ei]"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "mattin(ata|[aoe])"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleTheDayofmonth :: Rule+ruleTheDayofmonth = Rule+  { name = "il <day-of-month>"+  , pattern =+    [ regex "il|l'"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "(que)?st[oa]|i[nl]|(al|nel)(la)?|la"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "(in )?quest['oa]|per (il|l['a])"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "quest[oaie']"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleTwoTimeTokensSeparatedByDi :: Rule+ruleTwoTimeTokensSeparatedByDi = Rule+  { name = "two time tokens separated by `di`"+  , pattern =+    [ Predicate isNotLatent+    , regex "di"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTimeofdayCirca :: Rule+ruleTimeofdayCirca = Rule+  { name = "<time-of-day> circa"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "circa"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) (-1)+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "ieri"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "(in )?autunno"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleCircaPerLeTimeofday :: Rule+ruleCircaPerLeTimeofday = Rule+  { name = "circa per le <time-of-day>"+  , pattern =+    [ regex "(circa )?per( le)?|circa( alle)?|verso( le)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleVersoPartOfDay :: Rule+ruleVersoPartOfDay = Rule+  { name = "verso <part-of-day>"+  , pattern =+    [ regex "verso( la| il)?"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "((il )?giorno di )?natale"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNight :: Rule+ruleNight = Rule+  { name = "night"+  , pattern =+    [ regex "nott(e|ata)"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 1+          td2 = interval TTime.Open (hour False 0, hour False 4)+      in Token Time . partOfDay . mkLatent <$> intersect td1 td2+  }++ruleOgnissanti :: Rule+ruleOgnissanti = Rule+  { name = "ognissanti"+  , pattern =+    [ regex "(tutti i |ognis|festa dei |([ia]l )?giorno dei )santi"+    ]+  , prod = \_ -> tt $ monthDay 11 1+  }++ruleIntegerDelPartOfDay :: Rule+ruleIntegerDelPartOfDay = Rule+  { name = "<integer 0 12> del <part of day>"+  , pattern =+    [ Predicate $ isIntegerBetween 0 12+    , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))"+    ]+  , prod = \tokens -> case tokens of+      (Token Numeral (NumeralData {TNumeral.value = v}):_) ->+        tt $ hour False (12 + floor v)+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "di|del(l[a'])?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleGliNUltimiCycle :: Rule+ruleGliNUltimiCycle = Rule+  { name = "gli <n> ultimi <cycle>"+  , pattern =+    [ regex "([nd]e)?i|([nd]el)?le"+    , Predicate $ isIntegerBetween 2 9999+    , regex "(scors|ultim)[ei]"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "maggio|magg?\\.?"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "domenica|dom\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleDalleTimeofdayAlleTimeofdayInterval :: Rule+ruleDalleTimeofdayAlleTimeofdayInterval = Rule+  { name = "dalle <time-of-day> alle <time-of-day> (interval)"+  , pattern =+    [ regex "da(ll[ae'])?"+    , Predicate isATimeOfDay+    , regex "\\-|([fs]ino )?a(ll[ae'])?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "ottobre|ott\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleEntroLeTimeofday :: Rule+ruleEntroLeTimeofday = Rule+  { name = "entro le <time-of-day>"+  , pattern =+    [ regex "entro( l[ea'])?|prima d(i|ell['e])"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt . withDirection TTime.Before $ notLatent td+      _ -> Nothing+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "(([nd]el)?l')?ultim[oa]"+    , Predicate isADayOfWeek+    , regex "di|del(l[a'])?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleNameddayDayofmonth :: Rule+ruleNameddayDayofmonth = Rule+  { name = "<named-day> <day-of-month>"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleLastDayofweekOfTime2 :: Rule+ruleLastDayofweekOfTime2 = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "(l')ultim[oa]"+    , Predicate isADayOfWeek+    , regex "di"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd[/-]mm[/-]yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[/-](0?[1-9]|1[0-2])[/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTwoTimeTokensInARow :: Rule+ruleTwoTimeTokensInARow = Rule+  { name = "two time tokens in a row"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "novembre|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleIleNCyclePassatipassate :: Rule+ruleIleNCyclePassatipassate = Rule+  { name = "i|le n <cycle> passati|passate"+  , pattern =+    [ regex "([nd]e)?i|([nd]el)?le"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "(scors|passat)[ie]"+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mercoled(i|\x00ec)|mer\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "fine dell' ?anno"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "domani"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleNextNCycle2 :: Rule+ruleNextNCycle2 = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "([nd]e)?i|([nd]el)?le"+    , Predicate $ isIntegerBetween 2 9999+    , regex "prossim[ei]"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleProssimiUnitofduration :: Rule+ruleProssimiUnitofduration = Rule+  { name = "prossimi <unit-of-duration>"+  , pattern =+    [ regex "((([nd]e)?i|([nd]el)?le) )?prossim[ie]"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        let from = cycleNth grain 1+            to = cycleNth grain 3+        in tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "festa della mamma"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleFestaDelLavoro :: Rule+ruleFestaDelLavoro = Rule+  { name = "festa del lavoro"+  , pattern =+    [ regex "festa del lavoro|(festa|giorno) dei lavoratori"+    ]+  , prod = \_ -> tt $ monthDay 5 1+  }++ruleIntersectByDiDellaDel :: Rule+ruleIntersectByDiDellaDel = Rule+  { name = "intersect by \"di\", \"della\", \"del\""+  , pattern =+    [ Predicate isNotLatent+    , regex "di|del(la)?"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "settembre|sett?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAfternoon+  , ruleAtTimeofday+  , ruleChristmas+  , ruleChristmasEve+  , ruleCircaPerLeTimeofday+  , ruleCommemorazioneDeiDefunti+  , ruleDalDatetimeAlDatetimeInterval+  , ruleDalleTimeofdayAlleTimeofdayInterval+  , ruleDatetimeDatetimeInterval+  , ruleDayOfMonthSt+  , ruleDayofmonthNamedmonth+  , ruleDdddMonthInterval+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDimTimeAlPartofday+  , ruleDimTimeDelMattino+  , ruleDimTimePartofday+  , ruleDopoLeTimeofday+  , ruleDurationAgo+  , ruleEntroIlDuration+  , ruleEntroLeTimeofday+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEpifania+  , ruleEvening+  , ruleFerragosto+  , ruleFestaDelLavoro+  , ruleFestaDelPap+  , ruleFestaDellaLiberazione+  , ruleFestaDellaRepubblica+  , ruleFinoAlDatetimeInterval+  , ruleGliNUltimiCycle+  , ruleGliUltimiNCycle+  , ruleHalloweenDay+  , ruleHhRelativeminutesDelPomeriggiotimeofday+  , ruleHhRelativeminutesDelPomeriggiotimeofday2+  , ruleHhhmmTimeofday+  , ruleHhhmmTimeofday2+  , ruleHhmmMilitaryTimeofday+  , ruleHourofdayAndRelativeMinutes+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayMinusIntegerAsRelativeMinutes+  , ruleIlCycleDopoTime+  , ruleIlDayofmonthDeNamedmonth+  , ruleIlTime+  , ruleIleNCyclePassatipassate+  , ruleInDuration+  , ruleInNamedmonth+  , ruleInThePartofdayOfDimTime+  , ruleInafterDuration+  , ruleIntegerDelPartOfDay+  , ruleIntegerLatentTimeofday+  , ruleIntersectByDiDellaDel+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleLastDayofweekOfTime2+  , ruleLastTime+  , ruleLeIdiDiNamedmonth+  , ruleLunch+  , ruleMidnight+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNameddayDayofmonth+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextNCycle2+  , ruleNextTime+  , ruleNextTime2+  , ruleNight+  , ruleNoon+  , ruleNthTimeAfterTime+  , ruleNthTimeAfterTime2+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , ruleNthTimeOfTime3+  , ruleOgnissanti+  , ruleOrdinalCycleOfTime+  , rulePartofdayOfDimTime+  , ruleProssimiUnitofduration+  , ruleRelativeMinutesToIntegerAsHourofday+  , ruleRightNow+  , ruleSantoStefano+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleStamattina+  , ruleStanotte+  , ruleStasera+  , ruleTheCycleLast+  , ruleTheCycleNext+  , ruleTheCycleOfTime+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleTheDayofmonth+  , ruleTheLastCycle+  , ruleTheNthTimeOfTime+  , ruleTheOrdinalCycleOfTime+  , ruleThisCycle+  , ruleThisDayofweek+  , ruleThisPartofday+  , ruleThisTime+  , ruleTimeLast+  , ruleTimeNotte+  , ruleTimeNotte2+  , ruleTimeofdayCirca+  , ruleTimeofdayOra+  , ruleTimeofdayPrecise+  , ruleTimeofdayTimeofdayDayofmonthInterval+  , ruleTomorrow+  , ruleTraIlDatetimeEIlDatetimeInterval+  , ruleTwoTimeTokensInARow+  , ruleTwoTimeTokensSeparatedByDi+  , ruleUna+  , ruleValentinesDay+  , ruleWeekend+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYearNotLatent+  , ruleYesterday+  , ruleYyyymmdd+  , ruleHhThreeQuarterDelPomeriggiotimeofday+  , ruleHhThreeQuarterDelPomeriggiotimeofday2+  , ruleHourofdayMinusThreeQuarter+  , ruleThreeQuarterToIntegerAsHourofday+  , ruleHourofdayAndThreeQuarter+  , ruleHourofdayThreeQuarters+  , ruleHhQuartDelPomeriggiotimeofday+  , ruleHhQuartDelPomeriggiotimeofday2+  , ruleHourofdayMinusQuart+  , ruleQuartAsHourofday+  , ruleHourofdayAndAQuart+  , ruleHourofdayQuart+  , ruleHhHalfDelPomeriggiotimeofday+  , ruleHhHalfDelPomeriggiotimeofday2+  , ruleHourofdayMinusHalf+  , ruleHalfToIntegerAsHourofday+  , ruleHourofdayAndHalf+  , ruleHourofdayHalf+  , ruleHhIntegerminutesDelPomeriggiotimeofday+  , ruleHhIntegerminutesDelPomeriggiotimeofday2+  , ruleHourofdayMinusIntegerMinutes+  , ruleMinutesToIntegerAsHourofday+  , ruleHourofdayAndIntegerMinutes+  , ruleHourofdayIntegerMinutes+  , ruleTimezone+  , ruleTimeEntroLeTime+  , ruleImmacolataConcezione+  , ruleOrdinalQuarter+  , ruleTheOrdinalQuarter+  , ruleCycleOrdinalQuarterYear+  , ruleCycleTheOrdinalTime+  , ruleCycleNext+  , ruleDomattina+  , ruleVersoPartOfDay+  , ruleEntroIlInt+  , ruleEntroTime+  , ruleDalInt+  , ruleDopoTime+  , ruleToday+  , ruleDalIntAlInt+  , ruleTraIlIntEIlInt+  , ruleIlWeekendDelTime+  ]
+ Duckling/Time/KO/Corpus.hs view
@@ -0,0 +1,548 @@+-- 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.Time.KO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = KO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "방금"+             , "지금"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "오늘"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "어제"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "내일"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "월요일"+             , "이번주 월요일"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "2월18일 월요일"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "화요일"+             , "19일 화요일"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "목요일"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "금요일"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "토요일"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "일요일"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "3월 1일"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "3월 3일"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "2015년 3월 3일"+             , "이천십오년 삼월 삼일"+             , "2015/3/3"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15일에"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "2월 15일"+             , "2/15"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "8월 8일"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Month)+             [ "2014년 10월"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "1974/10/31"+             , "74/10/31"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "2015년 4월 14일"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "다음주 화요일"+             , "다음 화요일"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             [ "다음 3월"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "2월 18일 월요일"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "이번주"+             , "금주"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "저번주"+             , "전주"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "다음주"+             , "오는주"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Month)+             [ "저번달"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             [ "다음달"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "이번분기"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "다음분기"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "삼분기"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "2018년 4분기"+             ]+  , examples (datetime (2012, 1, 1, 0, 0, 0) Year)+             [ "작년"+             , "12년"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Year)+             [ "올해"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Year)+             [ "내년"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "저번주 일요일"+             , "지난주 일요일"+             , "지난 일요일"+             , "저번 일요일"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "저번주 화요일"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "다음주 화요일"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "다음주 수요일"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "다음주 금요일"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "이번주 월요일"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "이번주 화요일"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "이번주 수요일"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "내일모래"+             , "모래"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "내일 저녁다섯시"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "엊그제"+             , "그제"+             ]+  , examples (datetime (2013, 2, 10, 8, 0, 0) Hour)+             [ "엊그제 아침8시"+             , "엊그제 오전8시"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "3월 마지막 월요일"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "2014년 3월 마지막일요일"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "10월 3일"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "2014년 10월 첫번째주"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "2015년 10월 마지막날"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "2014년 9월 마지막주"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "10월 첫째화요일"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "2014년 9월 셋째화요일"+             , "2014년 9월 세번째화요일"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "2014년 10월 첫번째 수요일"+             , "2014년 10월 첫째 수요일"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "2014년 10월 두번째 수요일"+             , "2014년 10월 둘째 수요일"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "아침 3시"+             , "오전 세시"+             , "3AM"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18am"+             , "3:18a"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "오후 세시"+             , "3PM"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "오후세시이십분"+             , "3:20p"+             , "15:20"+             , "3:20pm"+             , "3:20PM"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "오후세시반"+             , "15:30"+             , "3:30pm"+             , "3:30PM"+             ]+  , examples (datetime (2013, 2, 12, 15, 45, 0) Minute)+             [ "네시십오분전"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "3:30"+             , "세시반"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             , "세시이십삼분이십사초"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "오늘밤 8시"+             , "저녁 8시"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "9월 20일 저녁 7시 30분"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "토요일 9시"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Hour)+             [ "2014년 7월 18일 금요일 오후 7시"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "1초안에"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "일분안에"+             , "일분내에"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "이분안에"+             , "이분내에"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "한시간안에"+             , "한시간내"+             ]+  , examples (datetime (2013, 2, 12, 6, 0, 0) Second)+             [ "한시간반안"+             , "한시간반내"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "두시간반안"+             , "두시간반내"+             ]+  , examples (datetime (2013, 2, 12, 7, 30, 0) Minute)+             [ "몇시간안"+             , "몇시간내"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 7, 30, 0) Minute)+             [ "몇시간후"+             , "몇시간이후"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "24시간안에"+             , "24시간내"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "하루안에"+             , "하루내"+             ]+  , examples (datetime (2016, 2, 1, 0, 0, 0) Month)+             [ "삼년안에"+             , "삼년내"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "7일안에"+             , "7일내"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "1주일안에"+             , "1주일내"+             ]+  , examples (datetime (2013, 2, 12, 6, 0, 0) Second)+             [ "약 한시간반 안에"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "7일전"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14일전"+             , "14일전에"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "3주전"+             , "3주이전"+             ]+  , examples (datetime (2011, 2, 1, 0, 0, 0) Month)+             [ "2년전"+             , "2년이전"+             ]+  , examples (datetime (1954, 1, 1, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "이번여름"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "이번겨울"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "크리스마스"+             ]+  , examples (datetime (2013, 12, 24, 0, 0, 0) Day)+             [ "크리스마스이브"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "신정"+             , "설날"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "삼일절"+             ]+  , examples (datetime (2013, 5, 5, 0, 0, 0) Day)+             [ "어린이날"+             ]+  , examples (datetime (2013, 6, 6, 0, 0, 0) Day)+             [ "현충일"+             ]+  , examples (datetime (2013, 6, 17, 0, 0, 0) Day)+             [ "제헌절"+             ]+  , examples (datetime (2013, 8, 15, 0, 0, 0) Day)+             [ "광복절"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "개천절"+             ]+  , examples (datetime (2013, 10, 9, 0, 0, 0) Day)+             [ "한글날"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "오늘저녁"+             , "오늘밤"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "저번주말"+             , "지난주말"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "내일저녁"+             , "내일밤"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "내일점심"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "어제저녁"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "이번주말"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "월요일 아침"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "2월 15일 아침"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "지난 2초"+             , "지난 이초"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ --"다음 3초" t14899520+               --"다음 삼초" t14899520+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "지난 2분"+             , "지난 이분"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "다음 3분"+             , "다음 삼분"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "지난 1시간"+             , "지난 한시간"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 4, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "지난 24시간"+             , "지난 스물네시간"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "다음 3시간"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ --"지난 2일" t14899546+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ --"다음 3일" t14899546+             --, "다음 몇일" t14899546+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "지난 2주"+             , "지난 이주"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "다음 3주"+             , "다음 삼주"+             ]+  , examples (datetimeInterval ((2012, 12, 1, 0, 0, 0), (2013, 2, 1, 0, 0, 0)) Month)+             [ "지난 2달"+             , "지난 두달"+             ]+  , examples (datetimeInterval ((2013, 3, 1, 0, 0, 0), (2013, 6, 1, 0, 0, 0)) Month)+             [ "다음 3달"+             , "다음 세달"+             ]+  , examples (datetimeInterval ((2011, 1, 1, 0, 0, 0), (2013, 1, 1, 0, 0, 0)) Year)+             [ --"지난 2년" t14899546+             --, "지난 이년" t14899546+             ]+  , examples (datetimeInterval ((2014, 1, 1, 0, 0, 0), (2017, 1, 1, 0, 0, 0)) Year)+             [ "다음 3년"+             , "다음 삼년"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "7월 13일 - 15일"+             , "7월 13일 부터 15일"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 14, 0, 0, 0)) Day)+             [ "8월 8일 - 8월 13일"+             , "8월 8일부터 8월 13일"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 부터 11:00"+             , "9:30 ~ 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "목요일 9:30 부터 11:00"+             , "목요일 9:30 ~ 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "목요일 오전9시 부터 오전11시"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-1:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "2주 이내에"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 12, 14, 0, 0)) Second)+             [ "오후 2시까지"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "4pm CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "목요일 8:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "오늘 오후두시에"+             , "오후두시에"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Hour)+             [ "4/25 오후4시에"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "내일 3pm"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "오후2시 이후"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "5일 후"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "오전11시 전"+             , "오전11시 이전"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "오후에"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "15분안"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 12, 0, 0) Hour)+             [ "점심이후"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "이번아침"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "오후12시"+             , "정오"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "오전12시"+             , "자정"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Month)+             [ "3월"+             , "3월에"+             ]+  ]
+ Duckling/Time/KO/Rules.hs view
@@ -0,0 +1,1358 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.KO.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "<named-day>에"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "\xc5d0"+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLiberationDay :: Rule+ruleLiberationDay = Rule+  { name = "Liberation Day"+  , pattern =+    [ regex "\xad11\xbcf5\xc808"+    ]+  , prod = \_ -> tt $ monthDay 8 15+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow - 내일모래"+  , pattern =+    [ regex "(\xb0b4\xc77c)?\xbaa8\xb798"+    ]+  , prod = \_ ->+      tt . cycleNthAfter False TG.Day 1 $ cycleNth TG.Day 1+  }++ruleConstitutionDay :: Rule+ruleConstitutionDay = Rule+  { name = "Constitution Day"+  , pattern =+    [ regex "\xc81c\xd5cc\xc808"+    ]+  , prod = \_ -> tt $ monthDay 6 17+  }++ruleTimeofday4 :: Rule+ruleTimeofday4 = Rule+  { name = "<time-of-day>이전"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(\xc774)?\xc804"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleDay :: Rule+ruleDay = Rule+  { name = "day"+  , pattern =+    [ Predicate isDOMInteger+    , regex "\xc77c"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleSinceTimeofday :: Rule+ruleSinceTimeofday = Rule+  { name = "since <time-of-day>"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\xc774\xb798\xb85c"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt . withDirection TTime.After $ predNth (- 1) False td+      _ -> Nothing+  }++ruleThisDayofweek :: Rule+ruleThisDayofweek = Rule+  { name = "this <day-of-week>"+  , pattern =+    [ regex "\xc774\xbc88(\xc8fc)?|\xae08\xc8fc"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "New Year's Day"+  , pattern =+    [ regex "\xc2e0\xc815|\xc124\xb0a0"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "\xc804|\xc800\xbc88|\xc9c0\xb09c"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|\\~|\xbd80\xd130"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ dimension Duration+    , regex "(\xc548|\xb0b4)(\xc5d0)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "\xbc29\xae08|\xc9c0\xae08|\xbc29\xae08|\xb9c9"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleMonth :: Rule+ruleMonth = Rule+  { name = "month"+  , pattern =+    [ Predicate $ isIntegerBetween 1 12+    , regex "\xc6d4"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ month v+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "\xbd04"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ dimension Time+    , regex "after next"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "\xc815\xc624"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "\xc624\xb298|\xb2f9\xc77c|\xae08\xc77c"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleIntegerHourofdayRelativeMinutes :: Rule+ruleIntegerHourofdayRelativeMinutes = Rule+  { name = "<integer> (hour-of-day) relative minutes 전"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "\xbd84\xc804"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> do+        v <- getIntValue token+        t <- minutesBefore v td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "\xbd84"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleHalfHourofdayRelativeMinutes :: Rule+ruleHalfHourofdayRelativeMinutes = Rule+  { name = "half (hour-of-day) relative minutes 전"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\xbc18\xc804"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleHourofdayHalfAsRelativeMinutes :: Rule+ruleHourofdayHalfAsRelativeMinutes = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\xbc18"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleSeconds :: Rule+ruleSeconds = Rule+  { name = "seconds"+  , pattern =+    [ Predicate $ isIntegerBetween 0 59+    , regex "\xcd08"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ second v+      _ -> Nothing+  }++ruleTimeOrdinalCycle :: Rule+ruleTimeOrdinalCycle = Rule+  { name = "<time> <ordinal> <cycle>"+  , pattern =+    [ dimension Time+    , dimension Ordinal+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token Ordinal od:Token TimeGrain grain:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday - 엊그제"+  , pattern =+    [ regex "(\xc5ca)?\xadf8(\xc81c|\xc7ac)"+    ]+  , prod = \_ ->+      tt . cycleNthAfter False TG.Day (-1) $ cycleNth TG.Day (-1)+  }++ruleDayofweek :: Rule+ruleDayofweek = Rule+  { name = "day-of-week"+  , pattern =+    [ regex "(\xc6d4|\xd654|\xc218|\xbaa9|\xae08|\xd1a0|\xc77c)(\xc694\xc77c|\xc69c)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xc6d4" -> tt $ dayOfWeek 1+        "\xd654" -> tt $ dayOfWeek 2+        "\xc218" -> tt $ dayOfWeek 3+        "\xbaa9" -> tt $ dayOfWeek 4+        "\xae08" -> tt $ dayOfWeek 5+        "\xd1a0" -> tt $ dayOfWeek 6+        "\xc77c" -> tt $ dayOfWeek 7+        _ -> Nothing+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "\xb2e4\xc74c|\xc624\xb294|\xcc28|\xb0b4"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "<named-month>에"+  , pattern =+    [ Predicate isAMonth+    , regex "\xc5d0"+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\xc815\xb3c4|\xcbe4"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ regex "\xc9c0\xae08\xbd80\xd130"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "\xc810\xc2ec"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "\xc9c0\xb09c|\xc791|\xc804|\xc800\xbc88"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "\xc624\xd6c4"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "(\xd06c\xb9ac\xc2a4\xb9c8\xc2a4)?\xc774\xbe0c"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "\xc5d0|\xb3d9\xc548"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ dimension Duration+    , regex "(\xc774)?\xd6c4"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\xc815\xac01"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "\xaca8\xc6b8"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "\xc5ec\xb984"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleDayWithKoreanNumeral :: Rule+ruleDayWithKoreanNumeral = Rule+  { name = "day with korean number - 십일..삼십일일"+  , pattern =+    [ regex "((\xc774|\xc0bc)?\xc2ed(\xc77c|\xc774|\xc0bc|\xc0ac|\xc624|\xc721|\xce60|\xd314|\xad6c)?)\xc77c"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (_:m1:m2:_)):_) ->+        let dozens = case m1 of+              "\xc774" -> 2+              "\xc0bc" -> 3+              _        -> 1+            units = case m2 of+              "\xc77c" -> 1+              "\xc774" -> 2+              "\xc0bc" -> 3+              "\xc0ac" -> 4+              "\xc624" -> 5+              "\xc721" -> 6+              "\xce60" -> 7+              "\xd314" -> 8+              "\xad6c" -> 9+              _        -> 1+        in tt . dayOfMonth $ 10 * dozens + units+      _ -> Nothing+  }++ruleDayWithKoreanNumeral2 :: Rule+ruleDayWithKoreanNumeral2 = Rule+  { name = "day with korean number - 일일..구일"+  , pattern =+    [ regex "(\xc77c|\xc774|\xc0bc|\xc0ac|\xc624|\xc721|\xce60|\xd314|\xad6c)\xc77c"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):_) -> case match of+        "\xc77c" -> tt $ dayOfMonth 1+        "\xc774" -> tt $ dayOfMonth 2+        "\xc0bc" -> tt $ dayOfMonth 3+        "\xc0ac" -> tt $ dayOfMonth 4+        "\xc624" -> tt $ dayOfMonth 5+        "\xc721" -> tt $ dayOfMonth 6+        "\xce60" -> tt $ dayOfMonth 7+        "\xd314" -> tt $ dayOfMonth 8+        "\xad6c" -> tt $ dayOfMonth 9+        _ -> Nothing+      _ -> Nothing+  }++ruleTimeofday2 :: Rule+ruleTimeofday2 = Rule+  { name = "<time-of-day>에"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\xc5d0"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "(\xc774)?\xc804"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "\xc9c0\xb09c"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleTimeNthTime :: Rule+ruleTimeNthTime = Rule+  { name = "<time> nth <time> - 3월 첫째 화요일"+  , pattern =+    [ dimension Time+    , dimension Ordinal+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td1 td2+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ dimension Duration+    , regex "\xc774\xb0b4(\xc5d0)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        let from = cycleNth TG.Second 0+            to = inDuration dd+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "\xc790\xc815"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "\xb300\xcda9|\xc57d"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleEndOfTime :: Rule+ruleEndOfTime = Rule+  { name = "end of <time>"+  , pattern =+    [ dimension Time+    , regex "\xb9d0"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "\xc8fc\xb9d0"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleTimeDayofweek :: Rule+ruleTimeDayofweek = Rule+  { name = "<time> 마지막 <day-of-week>"+  , pattern =+    [ dimension Time+    , regex "\xb9c8\xc9c0\xb9c9"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td2 td1+      _ -> Nothing+  }++ruleDate :: Rule+ruleDate = Rule+  { name = "<date>에"+  , pattern =+    [ dimension Time+    , regex "\xc5d0"+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "\xb2e4\xc74c|\xc624\xb294"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTimeCycle2 :: Rule+ruleTimeCycle2 = Rule+  { name = "<time> 마지막 <cycle>"+  , pattern =+    [ dimension Time+    , regex "\xb9c8\xc9c0\xb9c9"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:Token TimeGrain grain:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "\xb2e4\xc74c"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "\xc544\xce68"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "\xc774\xbc88|\xae08|\xc62c"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "\xc774\xbc88"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleTimeofday3 :: Rule+ruleTimeofday3 = Rule+  { name = "<time-of-day> 정각"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\xc815\xac01"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleMemorialDay :: Rule+ruleMemorialDay = Rule+  { name = "Memorial Day"+  , pattern =+    [ regex "\xd604\xcda9\xc77c"+    ]+  , prod = \_ -> tt $ monthDay 6 6+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "\xc5b4\xc81c"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "\xac00\xc744"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ Predicate $ liftM2 (||) isATimeOfDay isAPartOfDay+    , regex "\xc9c0\xb098\xc11c|(\xc774)?\xd6c4(\xc5d0)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt . notLatent $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "\xd06c\xb9ac\xc2a4\xb9c8\xc2a4"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(in the )?([ap])(\\s|\\.)?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (_:ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleTimeCycle :: Rule+ruleTimeCycle = Rule+  { name = "<time> 마지막 <cycle> "+  , pattern =+    [ dimension Time+    , regex "\xb9c8\xc9c0\xb9c9"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++-- (assoc (intersect (cycle-nth :day 0)+--                   (interval (hour (inc (:start %1)) false)+--                             (hour (inc (:end %1)) false) false))+--        :form :part-of-day)+ruleAfterPartofday :: Rule+ruleAfterPartofday = Rule+  { name = "after <part-of-day>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "\xc9c0\xb098\xc11c|\xd6c4\xc5d0"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleTimeofday :: Rule+ruleTimeofday = Rule+  { name = "time-of-day"+  , pattern =+    [ Predicate $ isIntegerBetween 0 24+    , regex "\xc2dc"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ hour True v+      _ -> Nothing+  }++ruleHangulDay :: Rule+ruleHangulDay = Rule+  { name = "Hangul Day"+  , pattern =+    [ regex "\xd55c\xae00\xb0a0"+    ]+  , prod = \_ -> tt $ monthDay 10 9+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleYearQuarter :: Rule+ruleYearQuarter = Rule+  { name = "<year> <1..4>quarter"+  , pattern =+    [ dimension Time+    , Predicate $ isIntegerBetween 1 4+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> do+        v <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (v - 1) td+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleChildrensDay :: Rule+ruleChildrensDay = Rule+  { name = "Children's Day"+  , pattern =+    [ regex "\xc5b4\xb9b0\xc774\xb0a0"+    ]+  , prod = \_ -> tt $ monthDay 5 5+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleByTime :: Rule+ruleByTime = Rule+  { name = "by <time> - 까지"+  , pattern =+    [ dimension Time+    , regex "\xae4c\xc9c0"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $+        interval TTime.Open (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleHhmmMilitaryAmpm :: Rule+ruleHhmmMilitaryAmpm = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):Token RegexMatch (GroupMatch (ap:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleQuarter :: Rule+ruleQuarter = Rule+  { name = "<1..4> quarter"+  , pattern =+    [ Predicate $ isIntegerBetween 1 4+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . cycleNthAfter False TG.Quarter (v - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|\\~|\xbd80\xd130"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNationalFoundationDay :: Rule+ruleNationalFoundationDay = Rule+  { name = "National Foundation Day"+  , pattern =+    [ regex "\xac1c\xcc9c\xc808"+    ]+  , prod = \_ -> tt $ monthDay 10 3+  }++ruleEveningnight :: Rule+ruleEveningnight = Rule+  { name = "evening|night"+  , pattern =+    [ regex "\xc800\xb141|\xbc24"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . partOfDay . mkLatent $+           interval TTime.Open (from, to)+  }++ruleIndependenceMovementDay :: Rule+ruleIndependenceMovementDay = Rule+  { name = "Independence Movement Day"+  , pattern =+    [ regex "\xc0bc\xc77c\xc808"+    ]+  , prod = \_ -> tt $ monthDay 3 1+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "(\\d{2,4})[-/](0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "\xb0b4\xc77c|\xba85\xc77c|\xb0bc"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleAmpmTimeofday :: Rule+ruleAmpmTimeofday = Rule+  { name = "am|pm <time-of-day>"+  , pattern =+    [ regex "(\xc624\xc804|\xc544\xce68|\xc624\xd6c4|\xc800\xb141)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (match:_)):+       Token Time td:+       _) -> tt . timeOfDayAMPM td $+         elem match ["\xc624\xc804", "\xc544\xce68"]+      _ -> Nothing+  }++ruleYear2 :: Rule+ruleYear2 = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1 2100+    , regex "\xb144"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterPartofday+  , ruleAfterTimeofday+  , ruleAfternoon+  , ruleAmpmTimeofday+  , ruleByTime+  , ruleChildrensDay+  , ruleChristmas+  , ruleChristmasEve+  , ruleConstitutionDay+  , ruleDate+  , ruleDatetimeDatetimeInterval+  , ruleDay+  , ruleDayWithKoreanNumeral+  , ruleDayWithKoreanNumeral2+  , ruleDayofweek+  , ruleDurationAgo+  , ruleDurationFromNow+  , ruleEndOfTime+  , ruleEveningnight+  , ruleExactlyTimeofday+  , ruleHangulDay+  , ruleHhmm+  , ruleHhmmMilitaryAmpm+  , ruleHhmmss+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayHalfAsRelativeMinutes+  , ruleInDuration+  , ruleIndependenceMovementDay+  , ruleInduringThePartofday+  , ruleIntegerHourofdayRelativeMinutes+  , ruleHalfHourofdayRelativeMinutes+  , ruleIntersect+  , ruleIntersectBy+  , ruleLastCycle+  , ruleLastNCycle+  , ruleLastTime+  , ruleLiberationDay+  , ruleLunch+  , ruleMemorialDay+  , ruleMidnighteodendOfDay+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMonth+  , ruleMorning+  , ruleNamedday+  , ruleNamedmonth+  , ruleNationalFoundationDay+  , ruleNewYearsDay+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNoon+  , ruleNow+  , ruleQuarter+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleSinceTimeofday+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleThisCycle+  , ruleThisDayofweek+  , ruleThisTime+  , ruleTimeAfterNext+  , ruleTimeCycle+  , ruleTimeCycle2+  , ruleTimeDayofweek+  , ruleTimeNthTime+  , ruleTimeOrdinalCycle+  , ruleTimePartofday+  , ruleTimeofday+  , ruleTimeofday2+  , ruleTimeofday3+  , ruleTimeofday4+  , ruleTimeofdayAmpm+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYear2+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYearQuarter+  , ruleYesterday+  , ruleYyyymmdd+  , ruleSeconds+  , ruleTimezone+  ]
+ Duckling/Time/NB/Corpus.hs view
@@ -0,0 +1,644 @@+-- 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.Time.NB.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = NB}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "nå"+             , "akkurat nå"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "i dag"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "i går"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "i morgen"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "mandag"+             , "man."+             , "på mandag"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Mandag den 18. februar"+             , "Man, 18 februar"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "tirsdag"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "torsdag"+             , "tors"+             , "tors."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "fredag"+             , "fre"+             , "fre."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "lørdag"+             , "lør"+             , "lør."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "søndag"+             , "søn"+             , "søn."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "Den første mars"+             , "1. mars"+             , "Den 1. mars"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "3 mars"+             , "den tredje mars"+             , "den 3. mars"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3 mars 2015"+             , "tredje mars 2015"+             , "3. mars 2015"+             , "3-3-2015"+             , "03-03-2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "På den 15."+             , "På den 15"+             , "Den 15."+             , "Den femtende"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "den 15. februar"+             , "15. februar"+             , "februar 15"+             , "15-02"+             , "15/02"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "8 Aug"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "Oktober 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             , "31-10-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14april 2015"+             , "April 14, 2015"+             , "fjortende April 15"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "neste fredag igjen"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "neste mars"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "neste mars igjen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "Søndag, 10 feb"+             , "Søndag 10 Feb"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Ons, Feb13"+             , "Ons feb13"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Mandag, Feb 18"+             , "Man, februar 18"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "denne uken"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "forrige uke"+             , "sist uke"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "neste uke"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "forrige måned"+             , "sist måned"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "neste måned"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "dette kvartalet"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "neste kvartal"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "tredje kvartal"+             , "3. kvartal"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4. kvartal 2018"+             , "fjerde kvartal 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "forrige år"+             , "sist år"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "i fjor"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "i år"+             , "dette år"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "neste år"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "forrige søndag"+             , "sist søndag"+             , "søndag i forrige uke"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "forrige tirsdag"+             , "sist tirsdag"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "neste tirsdag"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "neste onsdag"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "onsdag i neste uke"+             , "onsdag neste uke"+             , "neste onsdag igjen"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "neste fredag igjen"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "mandag denne uken"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "tirsdag denne uken"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "onsdag denne uken"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "i overimorgen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "i forigårs"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "siste mandag i mars"+             , "siste mandag i mars"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "siste søndag i mars 2014"+             , "siste søndag i mars 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "tredje dag i oktober"+             , "tredje dag i Oktober"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "første uke i oktober 2014"+             , "første uke i Oktober 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "siste dag i oktober 2015"+             , "siste dag i Oktober 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "siste uke i september 2014"+             , "siste uke i September 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "første tirsdag i oktober"+             , "første tirsdag i Oktober"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "tredje tirsdag i september 2014"+             , "tredje tirsdag i September 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "første onsdag i oktober 2014"+             , "første onsdag i Oktober 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "andre onsdag i oktober 2014"+             , "andre onsdag i Oktober 2014"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "klokken 3"+             , "kl. 3"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "klokken 15"+             , "kl. 15"+             , "15h"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "ca. kl. 15"+             , "cirka kl. 15"+             , "omkring klokken 15"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "imorgen klokken 17 sharp"+             , "imorgen kl. 17 presis"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "kvarter over 15"+             , "kvart over 15"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "kl. 20 over 15"+             , "klokken 20 over 15"+             , "kl. 15:20"+             , "15:20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "15:30"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "kvarter på 12"+             , "kvart på 12"+             , "11:45"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "klokken 9 på lørdag"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "Fre, Jul 18, 2014 19:00"+             ]+  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)+             [ "Fre, Jul 18"+             , "Jul 18, Fre"+             ]+  , examples (datetime (2014, 9, 20, 19, 30, 0) Minute)+             [ "kl. 19:30, Lør, 20 sep"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "om 1 sekund"+             , "om ett sekund"+             , "om et sekund"+             , "ett sekund fra nå"+             , "et sekund fra nå"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "om 1 minutt"+             , "om et minutt"+             , "om ett minutt"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "om 2 minutter"+             , "om to minutter"+             , "om 2 minutter mer"+             , "om to minutter mer"+             , "2 minutter fra nå"+             , "to minutter fra nå"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "om 60 minutter"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om en halv time"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "om 2,5 time"+             , "om 2 og en halv time"+             , "om to og en halv time"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "om én time"+             , "om 1 time"+             , "om 1t"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "om et par timer"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "om 24 timer"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "om en dag"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ "3 år fra i dag"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "om 7 dager"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "om en uke"+             , "om én uke"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om ca. en halv time"+             , "om cirka en halv time"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "7 dager siden"+             , "syv dager siden"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14 dager siden"+             , "fjorten dager siden"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "en uke siden"+             , "én uke siden"+             , "1 uke siden"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "3 uker siden"+             , "tre uker siden"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "3 måneder siden"+             , "tre måneder siden"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "to år siden"+             , "2 år siden"+             ]+  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetime (2013, 12, 0, 0, 0, 0) Month)+             [ "et år etter julaften"+             , "ett år etter julaften"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "denne sommeren"+             , "den her sommeren"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "denne vinteren"+             , "den her vinteren"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "1 juledag"+             , "1. juledag"+             , "første juledag"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "nyttårsaften"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "nyttårsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "i kveld"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "forrige helg"+             , "sist helg"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "i morgen kveld"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "i morgen middag"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "i går kveld"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "denne helgen"+             , "denne helga"+             , "i helga"+             , "i helgen"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "mandag morgen"+             ]+  , examples (datetimeInterval ((2013, 12, 24, 0, 0, 0), (2013, 12, 31, 0, 0, 0)) Day)+             [ "i romjulen"+             , "i romjula"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "siste 2 sekunder"+             , "siste to sekunder"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "neste 3 sekunder"+             , "neste tre sekunder"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "siste 2 minutter"+             , "siste to minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "neste 3 minutter"+             , "neste tre minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "siste 1 time"+             , "seneste 1 time"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "neste 3 timer"+             , "neste tre timer"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "siste 2 dager"+             , "siste to dager"+             , "seneste 2 dager"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "neste 3 dager"+             , "neste tre dager"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "siste 2 uker"+             , "siste to uker"+             , "seneste to uker"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "neste 3 uker"+             , "neste tre uker"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "siste 2 måneder"+             , "siste to måneder"+             , "seneste to måneder"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "neste 3 måneder"+             , "neste tre måneder"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "siste 2 år"+             , "siste to år"+             , "seneste 2 år"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "neste 3 år"+             , "neste tre år"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13-15 juli"+             , "13-15 Juli"+             , "13 til 15 Juli"+             , "13 juli til 15 juli"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "8 Aug - 12 Aug"+             , "8 Aug - 12 aug"+             , "8 aug - 12 aug"+             , "8 august - 12 august"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             , "9:30 til 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "fra 9:30 - 11:00 på torsdag"+             , "fra 9:30 til 11:00 på torsdag"+             , "mellom 9:30 og 11:00 på torsdag"+             , "9:30 - 11:00 på torsdag"+             , "9:30 til 11:00 på torsdag"+             , "etter 9:30 men før 11:00 på torsdag"+             , "torsdag fra 9:30 til 11:00"+             , "torsdag mellom 9:30 og 11:00"+             , "fra 9:30 til 11:00 på torsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "torsdag fra 9 til 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-13:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "innenfor 2 uker"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "innen kl. 14"+             , "innen klokken 14"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "16h CET"+             , "kl. 16 CET"+             , "klokken 16 CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "torsdag kl. 8:00 GMT"+             , "torsdag klokken 8:00 GMT"+             , "torsdag 08:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "idag kl. 14"+             , "idag klokken 14"+             , "kl. 14"+             , "klokken 14"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)+             [ "25/4 kl. 16:00"+             , "25/4 klokken 16:00"+             , "25-04 klokken 16:00"+             , "25-4 kl. 16:00"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Minute)+             [ "15:00 i morgen"+             , "kl. 15:00 i morgen"+             , "klokken 15:00 i morgen"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "etter kl. 14"+             , "etter klokken 14"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "etter 5 dager"+             , "etter fem dager"+             ]+  , examples (datetime (2013, 2, 17, 4, 0, 0) Hour)+             [ "om 5 dager"+             , "om fem dager"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 14, 0, 0) Hour)+             [ "etter i morgen kl. 14"+             , "etter i morgen klokken 14"+             , "i morgen etter kl. 14"+             , "i morgen etter klokken 14"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "før kl. 11"+             , "før klokken 11"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 11, 0, 0) Hour)+             [ "i morgen før kl. 11"+             , "i morgen før klokken 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "om ettermiddagen"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "kl. 13:30"+             , "klokken 13:30"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "om 15 minutter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "etter frokost"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)+             [ "denne morgen"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "neste mandag"+             ]+  , examples (datetime (2014, 2, 9, 0, 0, 0) Day)+             [ "morsdag"+             ]+  , examples (datetime (2013, 11, 10, 0, 0, 0) Day)+             [ "farsdag"+             ]+  ]
+ Duckling/Time/NB/Rules.hs view
@@ -0,0 +1,1965 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.NB.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "mandag|man\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "i overimorgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "desember|des\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "p\x00e5"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "(et)? ?(kvart)(er)? *p\x00e5"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "(et)? ?(kvart)(er)? *over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(et)? ?(kvart)(er)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:_) ->+        tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "halv time *p\x00e5"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "halv time *over"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "halv time"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:_) ->+        tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleConstitutionDay :: Rule+ruleConstitutionDay = Rule+  { name = "constitution day"+  , pattern =+    [ regex "grunnlovsdag(en)"+    ]+  , prod = \_ -> tt $ monthDay 5 17+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "tirsdag|tirs?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "valentine'?s?( dag)?"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleTheOrdinalCycleOfTime :: Rule+ruleTheOrdinalCycleOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "av|i|fra"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "af|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "nytt\x00e5rsdag"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(siste?|forrige|seneste)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "l\x00f8rdag|l\x00f8r\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|til|tilogmed"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juli|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "kveld(en)?"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleTheDayofmonthNonOrdinal :: Rule+ruleTheDayofmonthNonOrdinal = Rule+  { name = "the <day-of-month> (non ordinal)"+  , pattern =+    [ regex "den"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "om"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "akkurat n\x00e5|n\x00e5|(i )?dette \x00f8yeblikk"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "siste"+    , dimension TimeGrain+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "fra"+    , dimension Time+    , regex "\\-|til|tilogmed"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ regex "([012]?\\d|30|31)(ter|\\.)?"+    , regex "\\-|til"+    , regex "([012]?\\d|30|31)(ter|\\.)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (d1:_)):+       _:+       Token RegexMatch (GroupMatch (d2:_)):+       Token Time td:+       _) -> do+        dd1 <- parseInt d1+        dd2 <- parseInt d2+        dom1 <- intersect (dayOfMonth dd1) td+        dom2 <- intersect (dayOfMonth dd2) td+        tt $ interval TTime.Closed (dom1, dom2)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "torsdag|tors?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ regex "neste"+    , dimension Time+    , regex "igjen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "midten af"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "middag|(kl(\\.|okken)?)? tolv"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "i dag|idag"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "(kommende|neste)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "i forig\x00e5rs"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "mellom"+    , Predicate isATimeOfDay+    , regex "og"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "neste|kommende"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "januar|jan\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTheCycleOfTime :: Rule+ruleTheCycleOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|tet|et)? av"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(cirka|ca\\.|-?ish)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleOnDate :: Rule+ruleOnDate = Rule+  { name = "on <date>"+  , pattern =+    [ regex "den|p\x00e5"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mars|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "fra (i dag|idag|n\x00e5)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(til )?middag"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "siste?|seneste|forrige"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "ettermiddag(en)?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "april|apr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ regex "siste"+    , dimension Time+    , regex "igjen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-2) False td+      _ -> Nothing+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "julaften?"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "fredag|fre\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "etter"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour False v+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "av|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(etter|fra)"+    , Predicate isATimeOfDay+    , regex "((men )?f\x00f8r)|\\-|tilogmed|til"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "februar|feb\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "presis( kl.| klokken)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleInduringThePartofday2 :: Rule+ruleInduringThePartofday2 = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    , regex "en|ten"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "sommer(en)"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "mellom"+    , dimension Time+    , regex "og"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "nytt\x00e5rsaften?"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "siden"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "i slutten av"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $+        interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "etter jobb"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 17, hour False 21)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "siste?|seneste|forrige"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleChristmasDays :: Rule+ruleChristmasDays = Rule+  { name = "christmas days"+  , pattern =+    [ regex "romjul(a|en)"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 12 24, monthDay 12 30)+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(sharp|presis)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "innenfor"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        let from = cycleNth TG.Second 0+            to = inDuration dd+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "midnatt|EOD"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(omkring|cirka|ca\\.)( kl\\.| klokken)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "(engang )?innen|f\x00f8r|opptil"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "klokken|kl.|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juni|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "august|aug\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "((week(\\s|-)?end)|helg)(en|a)?"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "EOM"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleLastYear :: Rule+ruleLastYear = Rule+  { name = "Last year"+  , pattern =+    [ regex "i fjor"+    ]+  , prod = \_ -> tt . cycleNth TG.Year $ - 1+  }++ruleNthTimeAfterTime2 :: Rule+ruleNthTimeAfterTime2 = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "neste|kommende"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "i"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "neste"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleADuration :: Rule+ruleADuration = Rule+  { name = "a <duration>"+  , pattern =+    [ regex "(om )?en|ett|\x00e9n|et"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "morgen(en)?"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "i|denne"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time . partOfDay <$>+        intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "denne|dette|i|n\x00e5v\x00e6rende"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "(denne|dette|i|den her)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "av|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "etter (frokost|middag|lunsj|lunch)"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 13, hour False 17)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "p\x00e5 en"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $+       liftM2 (||) (isIntegerBetween (- 10000) 0) (isIntegerBetween 25 999)+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "i g\x00e5r|ig\x00e5r"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "vinter(en)"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "(engang )?etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "((1\\.?)|f\x00f8rste)? ?juledag"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNight :: Rule+ruleNight = Rule+  { name = "night"+  , pattern =+    [ regex "natt(en)?"+    ]+  , prod = \_ ->+      let from = hour False 0+          to = hour False 4+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "av|i|fra"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mai"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s\x00f8ndag|s\x00f8n\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute False h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "i kveld"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "oktober|okt\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "siste"+    , Predicate isADayOfWeek+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleFathersDay :: Rule+ruleFathersDay = Rule+  { name = "Father's Day"+  , pattern =+    [ regex "farsdag"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 11+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])[\\/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|tilogmed|til"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "november|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "etter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "onsdag|ons\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTheDayofmonthOrdinal :: Rule+ruleTheDayofmonthOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "den"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "f\x00f8r"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++rulePartofdayOfTime :: Rule+rulePartofdayOfTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "(en |ten )?den"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "EOY"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "i morgen|imorgen"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "morsdag"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 2+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "h"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "september|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         y <- parseInt match+         dom <- intersectDOM td token+         Token Time <$> intersect dom (year y)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond False h m s+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleADuration+  , ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterLunch+  , ruleAfterTimeofday+  , ruleAfterWork+  , ruleAfternoon+  , ruleAtTimeofday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleChristmasDays+  , ruleConstitutionDay+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEvening+  , ruleExactlyTimeofday+  , ruleFathersDay+  , ruleFromDatetimeDatetimeInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmss+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleInduringThePartofday2+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntersectByOfFromS+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLastYear+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNight+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeAfterTime2+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , ruleOnANamedday+  , ruleOnDate+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePartofdayOfTime+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleSeason+  , ruleSeason2+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheCycleOfTime+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleTheDayofmonthNonOrdinal+  , ruleTheDayofmonthOrdinal+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleTheOrdinalCycleOfTime+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleTimeofdaySharp+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleTonight+  , ruleUntilTimeofday+  , ruleValentinesDay+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleTimezone+  ]
+ Duckling/Time/PL/Corpus.hs view
@@ -0,0 +1,761 @@+-- 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.Time.PL.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = PL}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "teraz"+             , "w tej chwili"+             , "w tym momencie"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "dziś"+             , "dzis"+             , "dzisiaj"+             , "obecnego dnia"+             , "tego dnia"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "wczoraj"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "jutro"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "pojutrze"+             , "po jutrze"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "poniedziałek"+             , "pon."+             , "ten poniedziałek"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Poniedziałek, 18 Luty"+             , "Poniedziałek, Luty 18"+             , "Poniedziałek 18tego Lutego"+             , "Poniedziałek 18-tego Lutego"+             , "Poniedziałek, 18-tego Lutego"+             , "poniedzialek, 18go Lutego"+             , "Pon, 18 Luty"+             ]+  , examples (datetime (2013, 2, 2, 0, 0, 0) Day)+             [ "Sobota, 2ego Lutego"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "Wtorek"+             , "nastepny wtorek"+             , "wt."+             , "wtr."+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "czwartek"+             , "ten czwartek"+             , "czw"+             , "czw."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "piatek"+             , "ten piatek"+             , "pia"+             , "pia."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "sobota"+             , "ta sobota"+             , "sob"+             , "sob."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "niedziela"+             , "ta niedziela"+             , "niedz"+             , "niedz."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "pierwszy marca"+             , "pierwszego marca"+             , "marzec pierwszy"+             , "1szy marca"+             , "1szy marzec"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "marzec 3"+             , "marzec 3ci"+             , "3go marca"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3ci marca 2015"+             , "marzec 3ci 2015"+             , "3 marzec 2015"+             , "marzec 3 2015"+             , "trzeci marca 2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "15 Luty"+             , "15 Lutego"+             , "Luty 15"+             , "15-tego Lutego"+             , "2/15"+             , "Pietnastego Lutego"+             , "Piętnasty Luty"+             , "Luty Piętnastego"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "Sierpień 8"+             , "Sie 8"+             , "Sier 8"+             , "Sierp. 8"+             , "8 Sie."+             , "Ósmy Sie."+             , "Osmego Sie."+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "Październik 2014"+             , "Pazdziernika 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "10/31/1974"+             , "10/31/74"+             , "10-31-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14kwiecien 2015"+             , "Kwiecień 14, 2015"+             , "14tego Kwietnia 15"+             , "14-tego Kwietnia 15"+             , "14-ty Kwietnia 15"+             , "Czternasty Kwietnia 15"+             , "Czternastego Kwietnia 15"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "nastepny wtorek"+             , "kolejny wtorek"+             , "kolejnego wtorku"+             , "nastepnego wtorku"+             , "wtorek w przyszłym tygodniu"+             , "wtorek za tydzień"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "piatek po nastepnym"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nastepny Marzec"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "Marzec po nastepnym"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "Niedziela, 10 Luty"+             , "Niedziela, Luty 10"+             , "Niedziela, 10tego Luty"+             , "Niedziela, 10-tego Luty"+             , "Niedziela, 10-ty Lutego"+             , "Niedziela, 10tego Lutego"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Śr., Luty13"+             , "Śr., 13Luty"+             , "sr, 13Luty"+             , "sr, 13tego Lutego"+             , "Śro., 13Lutego"+             , "Środa trzynastego lutego"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Poniedziałek, Luty 18"+             , "Poniedziałek, 18 Lutego"+             , "Pon, Luty 18"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "ten tydzien"+             , "ten tydzień"+             , "ten tyg"+             , "tym tygodniu"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "ostatni tydzien"+             , "poprzedniego tygodnia"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "nastepny tydzien"+             , "nastepnego tygodnia"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "ostatni miesiac"+             , "poprzedni miesiac"+             , "poprzedniego miesiąca"+             , "po przedniego miesiąca"+             , "ostatniego miesiaca"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nastepnego miesiaca"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "ten kwartał"+             , "tego kwartału"+             , "tym kwartale"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "nastepny kwartał"+             , "następny kwartal"+             , "kolejnym kwartale"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "trzeci kwartał"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4ty kwartał 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "poprzedni rok"+             , "ostatni rok"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "ten rok"+             , "tym roku"+             , "obecny rok"+             , "w obecny rok"+             , "w obecnym roku"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "w kolejnym roku"+             , "kolejny rok"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "poprzednia niedziela"+             , "niedziela z ostatniego tygodnia"+             , "niedziela ostatniego tygodnia"+             , "niedziela poprzedniego tygodnia"+             , "ostatnia niedziela"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "ostatni wtorek"+             , "poprzedni wtorek"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "nastepny wtorek"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "nastepna środa"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "sroda nastepnego tygodnia"+             , "środa w przyszłym tygodniu"+             , "środa za tydzień"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "piatek nastepnego tygodnia"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "poniedzialek tego tygodnia"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "wtorek tego tygodnia"+             , "wtorek w tym tygodniu"+             , "ten wtorek"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "środa w tym tygodniu"+             , "ta środa"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "pojutrze"+             , "po jutrze"+             , "dzień po jutrze"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "dzień przed wczoraj"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "ostatni Poniedziałek Marca"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "ostatnia Niedziela w Marcu 2014"+             , "ostatnia Niedziela marca 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "trzeci dzień października"+             , "trzeci dzień w październiku"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "pierwszy tydzień października 2014"+             , "pierwszy tydzien w październiku 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "ostatni dzień w październiku 2015"+             , "ostatni dzień października 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "ostatni tydzień we wrześniu 2014"+             , "ostatni tydzień września 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "pierwszy wtorek w październiku"+             , "pierwszy wtorek października"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "trzeci wtorek we wrześniu 2014"+             , "trzeci wtorek września 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "pierwsza środa w październiku 2014"+             , "pierwsza środa października 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "druga środa w październiku 2014"+             , "druga środa października 2014"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "o 3 rano"+             , "3 rano"+             , "3 z rana"+             , "o trzeciej rano"+             , "o trzeciej z rana"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18 rano"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "o trzeciej"+             , "o 3 po południu"+             -- , "3 po południu" t14902576+             , "3 popołudniu"+             , "trzecia popoludniu"+             , "o trzeciej popoludniu"+             , "piętnasta godzina"+             , "15sta godzina"+             , "o piętnastej"+             , "o 15stej"+             ]+  , examples (datetime (2013, 2, 12, 18, 0, 0) Hour)+             [ -- "6 po południu" t14902576+               "6 popołudniu"+             , "szósta popoludniu"+             , "o szostej popoludniu"+             , "o 18stej"+             , "osiemnasta godzina"+             , "o osiemnastej"+             ]+  , examples (datetime (2013, 2, 12, 19, 0, 0) Hour)+             [ -- "7 po południu" t14902576+               "7 popołudniu"+             , "siódma popoludniu"+             , "o siodmej popoludniu"+             , "o dziewiętnastej"+             , "dziewietnasta godzina"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 wieczorem"+             , "8 popołudniu"+             , "osma w nocy"+             , "ósma wieczorem"+             , "dwudziesta godzina"+             ]+  , examples (datetime (2013, 2, 12, 21, 0, 0) Hour)+             [ "dziewiata wieczorem"+             , "dziewiąta popołudniu"+             , "dziewiata po południu"+             , "dziewiąta wieczorem"+             , "dziewiąta nocą"+             , "dziewiąta w nocy"+             , "9 wieczorem"+             , "9 popołudniu"+             -- , "9 po południu" t14902576+             , "9 wieczorem"+             , "9 nocą"+             , "9 w nocy"+             , "o dziewiatej w nocy"+             , "dwudziesta pierwsza godzina"+             , "dwudziestapierwsza godzina"+             ]+  , examples (datetime (2013, 2, 12, 22, 0, 0) Hour)+             [ "dziesiąta wieczorem"+             , "dziesiata popołudniu"+             , "dziesiata po południu"+             , "dziesiata wieczorem"+             , "dziesiata nocą"+             , "10 w nocy"+             , "o dziesiatej w nocy"+             , "o dwudziestej drugiej"+             ]+  , examples (datetime (2013, 2, 12, 23, 0, 0) Hour)+             [ "jedenasta wieczorem"+             , "jedenasta w nocy"+             , "11 w nocy"+             , "11 wieczorem"+             , "o jedenastej wieczorem"+             , "o dwudziestejtrzeciej"+             ]+  , examples (datetime (2013, 2, 13, 2, 0, 0) Hour)+             [ "jutro o drugiej"+             ]+  , examples (datetime (2013, 2, 14, 2, 0, 0) Hour)+             [ "po jutrze o drugiej"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "około 3 po południu"+             , "około trzeciej"+             , "koło trzeciej"+             , "o koło trzeciej"+             , "mniej wiecej o 3"+             , "tak o 15stej"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "jutro równo o piątej popołudniu"+             , "jutro równo o 17-stej"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "piętnaście po trzeciej"+             , "15 po trzeciej"+             , "kwadrans po 3"+             , "trzecia piętnaście"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "20 po 3"+             , "3:20"+             , "3:20 w poludnie"+             , "trzecia dwadzieścia"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "w pół do szesnastej"+             , "pol po trzeciej"+             , "15:30"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "3:30"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "kwadrans do południa"+             , "kwadrans przed południem"+             , "kwadrans do 12stej"+             , "11:45"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "8 wieczorem"+             , "8 tego wieczora"+             ]+  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)+             [ "o 7:30 popołudniu Piatek, 20 Wrzesień"+             , "o 7:30 popołudniu Piatek, Wrzesień 20"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "o 9 rano w Sobote"+             , "w Sobote na 9 rano"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "Pia, Lip 18, 2014 19:00"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "w sekundę"+             , "za sekundę"+             , "sekunde od teraz"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ -- "za minutę" t14902624+               "za jedną minutę"+             , "przez minutę"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "w 2 minuty"+             , "za jeszcze 2 minuty"+             , "2 minuty od teraz"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "w 60 minut"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "w pół godziny"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "w 2.5 godziny"+             , "w 2 i pół godziny"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "w godzinę"+             , "w 1h"+             , "w przeciągu godziny"+             ]+  , examples (datetime (2013, 2, 12, 7, 30, 0) Minute)+             [ "w kilka godzin"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "w 24 godziny"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "w jeden dzień"+             , "dzień od dziś"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ "3 lata od dziś"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "w 7 dni"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "w jeden tydzień"+             , "w tydzień"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "za około pół godziny"+             , "za jakieś pół godziny"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "7 dni temu"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14 dni temu"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "tydzien temu"+             , "jeden tydzień temu"+             , "1 tydzień temu"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "trzy tygodnie temu"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "trzy miesiące temu"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "dwa lata temu"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "7 dni potem"+             ]+  , examples (datetime (2013, 2, 26, 4, 0, 0) Hour)+             [ "14 dni później"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "tydzień później"+             , "jeden tydzień później"+             , "1 tydzień później"+             ]+  , examples (datetime (2013, 3, 5, 0, 0, 0) Day)+             [ "trzy tygodnie później"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "trzy miesiące później"+             ]+  , examples (datetime (2015, 2, 0, 0, 0, 0) Month)+             [ "dwa lata później"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "to lato"+             , "w to lato"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "ta zima"+             , "tej zimy"+             ]+  , examples (datetime (2013, 12, 24, 0, 0, 0) Day)+             [ "Wigilia Bożego Narodzenia"+             , "Wigilia"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "święta Bożego Narodzenia"+             , "boże narodzenie"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "sylwester"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "walentynki"+             ]+  , examples (datetime (2013, 5, 12, 0, 0, 0) Day)+             [ "Dzień Mamy"+             ]+  , examples (datetime (2013, 6, 16, 0, 0, 0) Day)+             [ "Dzień Taty"+             ]+  , examples (datetime (2013, 10, 31, 0, 0, 0) Day)+             [ "halloween"+             ]+  , examples (datetime (2013, 11, 28, 0, 0, 0) Day)+             [ "dzień dziękczynienia"+             , "dziękczynienie"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "ten wieczór"+             , "dzisiejszy wieczór"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "jutrzejszy wieczór"+             , "Środowy wieczór"+             , "jutrzejsza noc"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "wczorajszy wieczór"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "ten week-end"+             , "ten weekend"+             , "ten wekend"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "poniedziałkowy poranek"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "ostatnie 2 sekundy"+             , "ostatnie dwie sekundy"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "kolejne 3 sekundy"+             , "kolejne trzy sekundy"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "ostatnie 2 minuty"+             , "ostatnie dwie minuty"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "kolejne 3 minuty"+             , "nastepne trzy minuty"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "ostatnia 1 godzina"+             , "poprzednia jedna godzina"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "kolejne 3 godziny"+             , "kolejne trzy godziny"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "ostatnie 2 dni"+             , "ostatnie dwa dni"+             , "poprzednie 2 dni"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "nastepne 3 dni"+             , "nastepne trzy dni"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "nastepne kilka dni"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "ostatnie 2 tygodnie"+             , "ostatnie dwa tygodnie"+             , "poprzednie 2 tygodnie"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "nastepne 3 tygodnie"+             , "nastepne trzy tygodnie"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "ostatnie 2 miesiace"+             , "ostatnie dwa miesiące"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "nastepne trzy miesiące"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "ostatnie 2 lata"+             , "ostatnie dwa lata"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "nastepne 3 lata"+             , "kolejne trzy lata"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "Lipiec 13-15"+             , "Lipca 13 do 15"+             , "Lipiec 13 - Lipiec 15"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "Sie 8 - Sie 12"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "od 9:30 - 11:00 w Czwartek"+             -- , "miedzy 9:30 a 11:00 w czwartek" t14902649+             , "9:30 - 11:00 w czwartek"+             -- , "pozniej niż 9:30 ale przed 11:00 w Czwartek" t14902649+             , "Czwartek od 9:30 do 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "Czwartek od 9 rano do 11 rano"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-1:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "w ciągu 2 tygodni"+             , "w ciągu dwóch tygodni"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "przed drugą po południu"+             , "przed drugą"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "dziś o drugiej w południe"+             , "o drugiej popołudniu"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Hour)+             [ "4/25 o 4 popołudniu"+             , "4/25 o 16"+             , "4/25 o szesnastej"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)+             [ "3 popoludniu jutro"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "po drugiej po poludniu"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "po pięciu dniach"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "po drugiej po południu"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "przed 11 rano"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 11, 0, 0) Hour)+             [ "jutro przed 11 rano"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "to w południe"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "w 15 minut"+             , "w piętnaście minut"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "nastepny pon"+             , "kolejny poniedziałek"+             ]+  ]
+ Duckling/Time/PL/Rules.hs view
@@ -0,0 +1,1959 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.PL.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData(..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleOrdinalCycleTime :: Rule+ruleOrdinalCycleTime = Rule+  { name = "<ordinal> <cycle> <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "poniedzia(l|\x0142)(ek|ku|kowi|kiem|kowy)|pon\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "grudzie\x0144|grudzien|grudnia|grudniowi|grudniem|grudniu|gru\\.?|grud\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "do|przed"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "po"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "kwadrans(ie|owi|em|a)? *(do|przed)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "kwadrans(ie|owi|em|a)? *po"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "kwadrans(ie|owi|em|a)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "p(o|\x00f3)(l|\x0142) *(do|przed)"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "p(o|\x00f3)(l|\x0142) *po"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "p(o|\x00f3)(l|\x0142)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "wtorek|wtorku|wtorkowi|wtorkiem|wtr?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "walentynki"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?|(po ?)?przedni(ego|ch|emu|e|mi|m|a)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sobota|soboty|sobocie|sobot\x0119|sobote|sobot\x0105|sobota|sobocie|soboto|sob\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|(p|d)o|a(\x017c|z) (p|d)o"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "lipiec|lipca|lipcowi|lipcem|lipcu|lip\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "po"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "(w( ?(prze)?ci\x0105gu)?|za) ?(jeszcze)?|przez"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "(w)? ?(tym|tej)? ?(teraz|momencie|chwili|mome\x0144cie)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?"+    , dimension TimeGrain+    , regex "w(e)?|z(e)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "od|p(o|\x00f3)(z|\x017a)niej ni(z|\x017c)"+    , dimension Time+    , regex "\\-|do|po|a\x017c do|az do|a\x017c po|az po|ale przed"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleOrdinalAsHour :: Rule+ruleOrdinalAsHour = Rule+  { name = "<ordinal> (as hour)"+  , pattern =+    [ Predicate $ isOrdinalBetween 1 24+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt $ hour True v+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ Predicate isAMonth+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|do|po|a\x017c do|az do|a\x017c po|az po"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      ( Token Time td+       :Token RegexMatch (GroupMatch (d1:_))+       :_+       :Token RegexMatch (GroupMatch (d2:_))+       :_) -> do+        dd1 <- parseInt d1+        dd2 <- parseInt d2+        dom1 <- intersect (dayOfMonth dd1) td+        dom2 <- intersect (dayOfMonth dd2) td+        tt $ interval TTime.Closed (dom1, dom2)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "czwartek|czwartku|czwartkowi|czwartkiem|czwr?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "wiosna|wiosny|wio\x015bnie|wiosnie|wiosn\x0119|wiosne|wiosn\x0105|wiosna|wio\x015bnie|wiosnie|wiosno"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ dimension Time+    , regex "po kolejnym|po nast(e|\x0119)pn(ym|y|ego|emu|(a|\x0105)|ej|e)|po przysz(l|\x0142)(ym|y|ego|emu|(a|\x0105)|ej)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "the ides? of"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "po(l|\x0142)udni(em|e|a|u)"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "dzisiejszy|dzisiaj|dzi\x015b|dzis|w ten dzie\x0144|w ten dzien|w obecny dzie\x0144|w obecny dzien|obecnego dnia"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "kolejn(ym|y|ego|emu|e)|nast(e|\x0119)pn(ym|y|ego|emu|e|(a|\x0105)|ej|e)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "(po|po )?miedzy|mi\x0119dzy"+    , Predicate isATimeOfDay+    , regex "a|i"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "kolejn(ym|y|ego|emu|(a|\x0105)|ej|e)|nast(e|\x0119)pn(ym|y|ego|emu|(a|\x0105)|ej|e)|przysz(l|\x0142)(ego|emu|ym|(a|\x0105)|ej|ych|i|ymi|y|e)|za"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "stycze\x0144|styczen|stycznia|styczniowi|styczniem|styczniu|sty(cz)?\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTheCycleOfTime :: Rule+ruleTheCycleOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ regex "the"+    , dimension TimeGrain+    , regex "of"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "o?ko(l|\x0142)o|mniej wi(e|\x0119)cej"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++rulePolishIndependenceDay :: Rule+rulePolishIndependenceDay = Rule+  { name = "Polish independence day"+  , pattern =+    [ regex "(s|\x015b)wiet(a|o) niepodleg(l|\x0142)o(s|\x015b)ci|(\x015b|s)w\\.? niepodleg(l|\x0142)o(s|\x015b)ci"+    ]+  , prod = \_ -> tt $ monthDay 11 11+  }++ruleOnDate :: Rule+ruleOnDate = Rule+  { name = "on <date>"+  , pattern =+    [ regex "we?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "marzec|marca|marcowi|marcem|marcu|marz?\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleLastDayofweekTime :: Rule+ruleLastDayofweekTime = Rule+  { name = "last <day-of-week> <time>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?"+    , Predicate isADayOfWeek+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "od (dzi(s|\x015b)|teraz)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(na )?la?u?nc(z|h)|obiad"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej|e)?|(po ?)?przedni(ego|ch|emu|mi|m|e|(a|\x0105)|ej)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "po(l|\x0142)udni(em|e|a|u)"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleHourofdayHourofdayInterval :: Rule+ruleHourofdayHourofdayInterval = Rule+  { name = "<hour-of-day> - <hour-of-day> (interval)"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "-|do|a\x017c po|po"+    , Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "kwiecie\x0144|kwiecien|kwietnia|kwietniowi|kwietniem|kwietniu|kwiet?\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ dimension Time+    , regex "przed ?ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-2) False td+      _ -> Nothing+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "(wigilia|wigilii|wigili(e|\x0119)|wigili(a|\x0105)|wigilio) ?(bo(z|\x017c)ego narodzenia)?"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "(w|na) ?(czas(ie)?)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleThanksgivingDay :: Rule+ruleThanksgivingDay = Rule+  { name = "thanksgiving day"+  , pattern =+    [ regex "((s|\x015b)wiet(a|o)|(dzie(n|\x0144)))? ?dzi(e|\x0119)kczynieni(e|a)"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 4 4 11+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "pi\x0105tek|piatek|pi\x0105tku|piatku|pi\x0105tkowi|piatkowi|pi\x0105tkiem|piatkiem|pi(\x0105|a)tkowy|pia\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }+ruleIntersectBy2 :: Rule+ruleIntersectBy2 = Rule+  { name = "intersect by \",\" 2"+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "po"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) ->+        tt $ predNthAfter (TOrdinal.value od - 1) td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "po"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt . notLatent . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "of|in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(ni\x017c|niz|od)"+    , Predicate isATimeOfDay+    , regex "((but )?before)|\\-|do|po|a\x017c do|az do|a\x017c po|az po"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "luty|lutego|lutemu|lut?\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "(r(o|\x00f3)wno|dok(l|\x0142)adnie)( o)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "zima|zimy|zimie|zim\x0119|zime|zim\x0105|zima|zimie|zimo"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "lato|lata|latu|latem|lecie"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleIntegerLatentTimeofday :: Rule+ruleIntegerLatentTimeofday = Rule+  { name = "<integer> (latent time-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "(po|po )?mi(e|\x0119)dzy"+    , dimension Time+    , regex "a|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "sylwester|nowy rok"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "temu"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "do (ko[\x0144n]ca )?(tego)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $+        interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleDaybeforeyesterdaySingleword :: Rule+ruleDaybeforeyesterdaySingleword = Rule+  { name = "day-before-yesterday (single-word)"+  , pattern =+    [ regex "przedwczoraj"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej|e)?|(po ?)?przedni(ego|ch|emu|mi|m|e|(a|\x0105)|ej)?"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "r(o|\x00f3)wno|dok(l|\x0142)adnie"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "(w )?ci(a|\x0105)gu|zakresie|obr\x0119bie|obrebie"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        let from = cycleNth TG.Second 0+            to = inDuration dd+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleTimeofdayRano :: Rule+ruleTimeofdayRano = Rule+  { name = "<time-of-day> rano"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(z )?ran(o|a|u|em)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ timeOfDayAMPM td True+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "o?ko(l|\x0142)o|mniej wi(e|\x0119)cej|tak o"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "(a[\x017cz] )?do|przed"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "o|na|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "czerwiec|czerwca|czerwcowi|czerwcem|czerwcu|czer?\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "w(e)?|z(e)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "sierpie\x0144|sierpien|sierpnia|sierpniowi|sierpniem|sierpniu|sierp\\.?|sier\\.?|sie\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "((wek|week|wik)(\\s|-)?end|wkend)"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "(na |w )?(koniec|ko(n|\x0144)ca|ko(n|\x0144)cu|ko(n|\x0144)cowi|ko(n|\x0144)cem|ko(n|\x0144)c(o|\x00f3)wke) (miesi(a|\x0105)ca|msc)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "kolejn(ym|y|ego|emu|(a|\x0105)|ej|e)|nast(e|\x0119)pn(ym|y|ego|emu|e|(a|\x0105)|ej|e)|przysz(l|\x0142)(ego|emu|ym|(a|\x0105)|ej|ych|i|ymi|y|e)"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleDayaftertomorrowSingleword :: Rule+ruleDayaftertomorrowSingleword = Rule+  { name = "day-after-tomorrow (single-word)"+  , pattern =+    [ regex "(po ?jutr(o|ze))"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "the"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "z"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "kolejn(ym|y|ego|emu|(a|\x0105)|ej|e)|nast(e|\x0119)pn(ym|y|ego|emu|(a|\x0105)|ej|e)"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "rano|poran(ek|ku|ka)|z rana|(s|\x015b)witem"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "ten|tego|ta|to"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "te(mu|n|go|j)|tym|t(a|\x0105)|nadchodz(a|\x0105)c(ym|y|ego|emu|(a|\x0105)|ej)|obecn(ym|y|emu|ego|nym|(a|\x0105)|ej)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "te(mu|n|go|j)|ta|to|tym|nadchodz(a|\x0105)c(ym|y|ego|emu|(a|\x0105)|ej)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDurationHence :: Rule+ruleDurationHence = Rule+  { name = "<duration> hence"+  , pattern =+    [ dimension Duration+    , regex "p(o|\x00f3)(z|\x017a)niej|potem"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "of|in"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNthTimeTime :: Rule+ruleNthTimeTime = Rule+  { name = "nth <time> <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token Time td1:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleTimeofdayPopoudniuwieczoremwNocy :: Rule+ruleTimeofdayPopoudniuwieczoremwNocy = Rule+  { name = "<time-of-day> popołudniu/wieczorem/w nocy"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(w )?noc(y|(a|\x0105))|(po ?)?po(l|\x0142)udni(em|e|a|u)|wiecz(o|\x00f3)r(i|u|a|owi|em|rze)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ timeOfDayAMPM td False+      _ -> Nothing+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "we?"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+         n <- getIntValue token+         tt . mkLatent $ year n+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "wczoraj(szym|szy)?|wczrj|wczor"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "jesie\x0144|jesien|jesieni|jesieni\x0105|jesienia"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "po"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "((\x015a|\x015b|s)wi(e|\x0119)ta)? ?bo(z|\x017c)(ym|ego|e) narodzeni(e|a|u)"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "after"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "w(e)?|z(e)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "maj|maja|majowi|majem|maju"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "niedziela|niedzieli|niedziel\x0119|niedziele|niedziela|niedziel\x0105|niedzieli|niedzielo|nied?z?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleFromHourofdayHourofdayInterval :: Rule+ruleFromHourofdayHourofdayInterval = Rule+  { name = "from <hour-of-day> - <hour-of-day> (interval)"+  , pattern =+    [ regex "od"+    , Predicate isATimeOfDay+    , regex "-|to|th?ru|through|until"+    , Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "pa(z|\x017a)dziernik(a|owi|iem|u)?|pa\x017a\\.?|paz\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en( day)?"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleHhmmMilitary :: Rule+ruleHhmmMilitary = Rule+  { name = "hhmm (military)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . mkLatent $ hourMinute False h m+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?"+    , Predicate isADayOfWeek+    , regex "w(e)?|z(e)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleFathersDay :: Rule+ruleFathersDay = Rule+  { name = "Father's Day"+  , pattern =+    [ regex "dzie(n|\x0144) ?(taty|ojca)"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 2 7 6+  }++ruleLastCycleTime :: Rule+ruleLastCycleTime = Rule+  { name = "last <cycle> <time>"+  , pattern =+    [ regex "ostatni(ego|ch|emu|mi|m|(a|\x0105)|ej)?"+    , dimension TimeGrain+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleByTime :: Rule+ruleByTime = Rule+  { name = "by <time>"+  , pattern =+    [ regex "(a(z|\x017c) )?do"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Open (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleHhmmMilitaryAmpm :: Rule+ruleHhmmMilitaryAmpm = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):+       Token RegexMatch (GroupMatch (ap:_)):+       _) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "przed"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|:|do|po|a\x017c do|az do|a\x017c po|az po"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "listopad|listopada|listopadowi|listopadem|listopadzie|lis\\.?|list\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "po"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleEveningnight :: Rule+ruleEveningnight = Rule+  { name = "evening|night"+  , pattern =+    [ regex "wiecz(o|\x00f3)r(em|owi|ze|a|u)?|noc(\x0105)?"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "(\x015a|\x015b|s)rod(a|\x0105|y|e|\x0119|zie|owy|o)|(s|\x015b|\x015a)ro?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "do|przed"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])[-/](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "(na |w )?(koniec|ko(n|\x0144)ca|ko(n|\x0144)cu|ko(n|\x0144)cowi|ko(n|\x0144)cem|ko(n|\x0144)c(o|\x00f3)wke) (rok(u|owi|iem))"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "jutr(o|a|u|em|ze(jszy|jsza)?)|jtr|jutr"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "dzie(n|\x0144) ? ma(my|tki|m)"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "godzina"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "wrzesie\x0144|wrzesien|wrze\x015bnia|wrzesnia|wrze\x015bniowi|wrzesniowi|wrzesie\x0144|wrzesien|wrze\x015bniem|wrzesniem|wrze\x015bniu|wrzesniu|wrz\\.?|wrze\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         y <- parseInt match+         dom <- intersectDOM td token+         Token Time <$> intersect dom (year y)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterTimeofday+  , ruleAfternoon+  , ruleAtTimeofday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleByTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayaftertomorrowSingleword+  , ruleDaybeforeyesterdaySingleword+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleDurationHence+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEveningnight+  , ruleExactlyTimeofday+  , ruleFathersDay+  , ruleFromDatetimeDatetimeInterval+  , ruleFromHourofdayHourofdayInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmMilitary+  , ruleHhmmMilitaryAmpm+  , ruleHhmmss+  , ruleHourofdayHourofdayInterval+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleIntegerLatentTimeofday+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntersectBy2+  , ruleIntersectByOfFromS+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastCycleTime+  , ruleLastDayofweekOfTime+  , ruleLastDayofweekTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLunch+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeOfTime+  , ruleNthTimeTime+  , ruleOnANamedday+  , ruleOnDate+  , ruleOrdinalAsHour+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalCycleTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePolishIndependenceDay+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleThanksgivingDay+  , ruleTheCycleOfTime+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimeofdayApproximately+  , ruleTimeofdayOclock+  , ruleTimeofdayPopoudniuwieczoremwNocy+  , ruleTimeofdayRano+  , ruleTimeofdaySharp+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleUntilTimeofday+  , ruleValentinesDay+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleTimezone+  ]
+ Duckling/Time/PT/Corpus.hs view
@@ -0,0 +1,475 @@+-- 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.Time.PT.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = PT}, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext {lang = PT}, examples)+  where+    examples =+      [ "no 987"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "agora"+             , "já"+             , "ja"+             , "nesse instante"+             , "neste instante"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "hoje"+             , "nesse momento"+             , "neste momento"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "ontem"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "antes de ontem"+             , "anteontem"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "amanhã"+             , "amanha"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "depois de amanhã"+             , "depois de amanha"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "segunda-feira"+             , "segunda feira"+             , "segunda"+             , "seg."+             , "seg"+             , "essa segunda-feira"+             , "essa segunda feira"+             , "essa segunda"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "segunda, 18 de fevereiro"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "terça-feira"+             , "terça feira"+             , "terça"+             , "terca-feira"+             , "terca feira"+             , "terca"+             , "ter."+             , "ter"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "quarta-feira"+             , "quarta feira"+             , "quarta"+             , "qua."+             , "qua"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "quinta-feira"+             , "quinta feira"+             , "quinta"+             , "qui."+             , "qui"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "sexta-feira"+             , "sexta feira"+             , "sexta"+             , "sex."+             , "sex"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "sábado"+             , "sabado"+             , "sáb."+             , "sáb"+             , "sab."+             , "sab"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "domingo"+             , "dom."+             , "dom"+             ]+  , examples (datetime (2013, 5, 5, 0, 0, 0) Day)+             [ "5 de maio"+             , "cinco de maio"+             ]+  , examples (datetime (2013, 5, 5, 0, 0, 0) Day)+             [ "cinco de maio de 2013"+             , "5 de maio de 2013"+             , "5/5"+             , "5/5/2013"+             ]+  , examples (datetime (2013, 7, 4, 0, 0, 0) Day)+             [ "4 de julho"+             , "quatro de julho"+             , "4/7"+             , "4/7/2013"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "3 de março"+             , "três de março"+             , "tres de março"+             , "3/3"+             , "3/3/2013"+             ]+  , examples (datetime (2013, 4, 5, 0, 0, 0) Day)+             [ "5 de abril"+             , "cinco de abril"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1 de março"+             , "primeiro de março"+             , "um de março"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1-3-2013"+             , "1.3.2013"+             , "1/3/2013"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "essa dia 16"+             , "16 de fevereiro"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "este dia 17"+             , "17 de fevereiro"+             , "17/2"+             , "no domingo"+             , "no dia 17"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "esse dia 20"+             , "20 de fevereiro"+             , "20/2"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "próxima terça-feira"+             , "próxima terça feira"+             , "próxima terça"+             , "proxima terça-feira"+             , "proxima terça feira"+             , "proxima terça"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "quarta que vem"+             , "quarta da semana que vem"+             , "quarta da próxima semana"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "terça desta semana"+             , "terça dessa semana"+             , "terça agora"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "esta semana"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "semana passada"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "semana que vem"+             , "proxima semana"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "mês passado"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "mes que vem"+             , "próximo mês"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "ano passado"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "este ano"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "ano que vem"+             , "proximo ano"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "domingo passado"+             , "domingo da semana passada"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "terça passada"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "às tres da tarde"+             , "às tres"+             , "às 3 pm"+             , "às 15 horas"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "às oito da noite"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Minute)+             [ "15:00"+             , "15.00"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Hour)+             [ "meianoite"+             , "meia noite"+             ]+  , examples (datetime (2013, 2, 12, 12, 0, 0) Hour)+             [ "meio dia"+             , "meiodia"+             ]+  , examples (datetime (2013, 2, 12, 12, 15, 0) Minute)+             [ "meio dia e quinze"+             ]+  , examples (datetime (2013, 2, 12, 11, 55, 0) Minute)+             [ "5 para meio dia"+             ]+  , examples (datetime (2013, 2, 12, 12, 30, 0) Minute)+             [ "meio dia e meia"+             ]+  , examples (datetime (2013, 2, 12, 6, 0, 0) Hour)+             [ "as seis da manha"+             , "as seis pela manha"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "às tres e quinze"+             , "às tres e quinze da tarde"+             , "às tres e quinze pela tarde"+             , "15:15"+             , "15.15"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "às tres e meia"+             , "às 3 e trinta"+             , "às tres e meia da tarde"+             , "às 3 e trinta da tarde"+             , "15:30"+             , "15.30"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "quinze para meio dia"+             , "quinze para o meio dia"+             , "11:45"+             , "as onze e quarenta e cinco"+             , "hoje quinze para o meio dia"+             , "hoje às onze e quarenta e cinco"+             ]+  , examples (datetime (2013, 2, 12, 5, 15, 0) Minute)+             [ "5 e quinze"+             ]+  , examples (datetime (2013, 2, 12, 6, 0, 0) Hour)+             [ "6 da manhã"+             ]+  , examples (datetime (2013, 2, 13, 11, 0, 0) Hour)+             [ "quarta às onze da manhã"+             ]+  , examples (datetime (2014, 9, 12, 0, 0, 0) Day)+             [ "sexta, 12 de setembro de 2014"+             , "sexta feira, 12 de setembro de 2014"+             , "12 de setembro de 2014, sexta"+             , "12 de setembro de 2014 sexta feira"+             , "sexta feira 12 de setembro de 2014"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "em um segundo"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "em um minuto"+             , "em 1 min"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "em 2 minutos"+             , "em dois minutos"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "em 60 minutos"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "em uma hora"+             ]+  , examples (datetime (2013, 2, 12, 2, 30, 0) Minute)+             [ "fazem duas horas"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "em 24 horas"+             , "em vinte e quatro horas"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "em um dia"+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "em 7 dias"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "em uma semana"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "faz tres semanas"+             , "faz três semanas"+             ]+  , examples (datetime (2013, 4, 12, 0, 0, 0) Day)+             [ "em dois meses"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "faz tres meses"+             ]+  , examples (datetime (2014, 2, 0, 0, 0, 0) Month)+             [ "em um ano"+             , "em 1 ano"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "faz dois anos"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "este verão"+             , "este verao"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "este inverno"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "Natal"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "véspera de ano novo"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "ano novo"+             , "reveillon"+             , "Reveillon"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "esta noite"+             , "essa noite"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "amanhã a noite"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "ontem a noite"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "este final de semana"+             , "este fim de semana"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "segunda de manhã"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "dia 15 de fevereiro pela manhã"+             , "dia 15 de fevereiro de manhã"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "às 8 da noite"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "2 segundos atras"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "proximos 3 segundos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "2 minutos atrás"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "proximos 3 minutos"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "proximas 3 horas"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "passados 2 dias"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "proximos 3 dias"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "duas semanas atras"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "3 proximas semanas"+             , "3 semanas que vem"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "passados 2 meses"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "3 próximos meses"+             , "proximos tres meses"+             , "tres meses que vem"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "passados 2 anos"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "3 próximos anos"+             , "proximo tres anos"+             , "3 anos que vem"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13 a 15 de julho"+             , "13 - 15 de julho de 2013"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 0, 0)) Minute)+             [ "9:30 - 11:00"+             ]+  , examples (datetimeInterval ((2013, 12, 21, 0, 0, 0), (2014, 1, 7, 0, 0, 0)) Day)+             [ "21 de Dez. a 6 de Jan"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 12, 7, 30, 0)) Second)+             [ "dentro de tres horas"+             ]+  , examples (datetime (2013, 2, 12, 16, 0, 0) Hour)+             [ "as quatro da tarde"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "as quatro CET"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 12, 0, 0) Hour)+             [ "após ao meio dia"+             , "depois do meio dia"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 12, 0, 0) Hour)+             [ "antes do meio dia"+             , "não mais que meio dia"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 15, 0, 0) Hour)+             [ "amanhã depois das 15hs"+             , "amanha após as quinze horas"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 0, 0, 0) Hour)+             [ "antes da meia noite"+             , "até a meia noite"+             ]+  ]
+ Duckling/Time/PT/Rules.hs view
@@ -0,0 +1,1655 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.PT.Rules+  ( rules ) where++import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "segunda((\\s|\\-)feira)?|seg\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleSHourmintimeofday :: Rule+ruleSHourmintimeofday = Rule+  { name = "às <hour-min>(time-of-day)"+  , pattern =+    [ regex "(\x00e0|a)s?"+    , Predicate isATimeOfDay+    , regex "horas?"+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "depois de amanh(\x00e3|a)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "dezembro|dez\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "ter(\x00e7|c)a((\\s|\\-)feira)?|ter\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleNatal :: Rule+ruleNatal = Rule+  { name = "natal"+  , pattern =+    [ regex "natal"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNaoDate :: Rule+ruleNaoDate = Rule+  { name = "n[ao] <date>"+  , pattern =+    [ regex "n[ao]"+    , Predicate $ isGrainOfTime TG.Day+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleIntersectByDaOrDe :: Rule+ruleIntersectByDaOrDe = Rule+  { name = "intersect by `da` or `de`"+  , pattern =+    [ Predicate isNotLatent+    , regex "d[ae]"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++rulePassadosNCycle :: Rule+rulePassadosNCycle = Rule+  { name = "passados n <cycle>"+  , pattern =+    [ regex "passad(a|o)s?"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(\x00fa|u)ltim[ao]s?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s(\x00e1|a)bado|s(\x00e1|a)b\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|a"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "julho|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "noite"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayOfMonthSt :: Rule+ruleDayOfMonthSt = Rule+  { name = "day of month (1st)"+  , pattern =+    [ regex "primeiro|um|1o"+    ]+  , prod = \_ -> tt $ dayOfMonth 1+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "(hoje)|(neste|nesse) momento"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleDimTimeDaMadrugada :: Rule+ruleDimTimeDaMadrugada = Rule+  { name = "<dim time> da madrugada"+  , pattern =+    [ dimension Time+    , regex "(da|na|pela) madruga(da)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let td2 = mkLatent . partOfDay $+                    interval TTime.Open (hour False 1, hour False 4)+        in Token Time <$> intersect td td2+      _ -> Nothing+  }++ruleHhhmmTimeofday :: Rule+ruleHhhmmTimeofday = Rule+  { name = "hh(:|.|h)mm (time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:h\\.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "quinta((\\s|\\-)feira)?|qui\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleProximoCycle :: Rule+ruleProximoCycle = Rule+  { name = "proximo <cycle> "+  , pattern =+    [ regex "pr(\x00f3|o)xim(o|a)s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleCycleAntesDeTime :: Rule+ruleCycleAntesDeTime = Rule+  { name = "<cycle> antes de <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "antes d[eo]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleEsteCycle :: Rule+ruleEsteCycle = Rule+  { name = "este <cycle>"+  , pattern =+    [ regex "(n?es[st](es?|as?))"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleSHourminTimeofday :: Rule+ruleSHourminTimeofday = Rule+  { name = "às <hour-min> <time-of-day>"+  , pattern =+    [ regex "(\x00e0|a)s"+    , Predicate isNotLatent+    , regex "da"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "primavera"+    ]+  , prod = \_ ->+      let from = monthDay 3 20+          to = monthDay 6 21+      in tt $ interval TTime.Open (from, to)+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleDiaDayofmonthDeNamedmonth :: Rule+ruleDiaDayofmonthDeNamedmonth = Rule+  { name = "dia <day-of-month> de <named-month>"+  , pattern =+    [ regex "dia"+    , Predicate isDOMInteger+    , regex "de|\\/"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "meio[\\s\\-]?dia"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleProximasNCycle :: Rule+ruleProximasNCycle = Rule+  { name = "proximas n <cycle>"+  , pattern =+    [ regex "pr(\x00f3|o)xim(o|a)s?"+    , Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "es[ts][ae]|pr(\x00f3|o)xim[ao]"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "anteontem|antes de ontem"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleHourofdayAndRelativeMinutes :: Rule+ruleHourofdayAndRelativeMinutes = Rule+  { name = "<hour-of-day> and <relative minutes>"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleIntegerParaAsHourofdayAsRelativeMinutes :: Rule+ruleIntegerParaAsHourofdayAsRelativeMinutes = Rule+  { name = "<integer> para as <hour-of-day> (as relative minutes)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "para ((o|a|\x00e0)s?)?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes2 :: Rule+ruleHourofdayIntegerAsRelativeMinutes2 = Rule+  { name = "<hour-of-day> <integer> (as relative minutes) minutos"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleHourofdayAndRelativeMinutes2 :: Rule+ruleHourofdayAndRelativeMinutes2 = Rule+  { name = "<hour-of-day> and <relative minutes> minutos"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e"+    , Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }+ruleIntegerParaAsHourofdayAsRelativeMinutes2 :: Rule+ruleIntegerParaAsHourofdayAsRelativeMinutes2 = Rule+  { name = "<integer> minutos para as <hour-of-day> (as relative minutes)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "min\\.?(uto)?s?"+    , regex "para ((o|a|\x00e0)s?)?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "quinze"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }+ruleHourofdayAndQuarter :: Rule+ruleHourofdayAndQuarter = Rule+  { name = "<hour-of-day> and quinze"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e quinze"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }+ruleQuarterParaAsHourofdayAsRelativeMinutes :: Rule+ruleQuarterParaAsHourofdayAsRelativeMinutes = Rule+  { name = "quinze para as <hour-of-day> (as relative minutes)"+  , pattern =+    [ regex "quinze para ((o|a|\x00e0)s?)?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "meia|trinta"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }+ruleHourofdayAndHalf :: Rule+ruleHourofdayAndHalf = Rule+  { name = "<hour-of-day> and half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e (meia|trinta)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }+ruleHalfParaAsHourofdayAsRelativeMinutes :: Rule+ruleHalfParaAsHourofdayAsRelativeMinutes = Rule+  { name = "half para as <hour-of-day> (as relative minutes)"+  , pattern =+    [ regex "(meia|trinta) para ((o|a|\x00e0)s?)?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleHourofdayThreeQuarter :: Rule+ruleHourofdayThreeQuarter = Rule+  { name = "<hour-of-day> 3/4 (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "quarenta e cinco"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 45+      _ -> Nothing+  }+ruleHourofdayAndThreeQuarter :: Rule+ruleHourofdayAndThreeQuarter = Rule+  { name = "<hour-of-day> and 3/4"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "e quarenta e cinco"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 45+      _ -> Nothing+  }+ruleThreeQuarterParaAsHourofdayAsRelativeMinutes :: Rule+ruleThreeQuarterParaAsHourofdayAsRelativeMinutes = Rule+  { name = "3/4 para as <hour-of-day> (as relative minutes)"+  , pattern =+    [ regex "quarenta e cinco para ((o|a|\x00e0)s?)?"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> Token Time <$> minutesBefore 45 td+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "janeiro|jan\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTiradentes :: Rule+ruleTiradentes = Rule+  { name = "Tiradentes"+  , pattern =+    [ regex "tiradentes"+    ]+  , prod = \_ -> tt $ monthDay 4 21+  }++ruleInThePartofday :: Rule+ruleInThePartofday = Rule+  { name = "in the <part-of-day>"+  , pattern =+    [ regex "(de|pela)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++rulePartofdayDessaSemana :: Rule+rulePartofdayDessaSemana = Rule+  { name = "<part-of-day> dessa semana"+  , pattern =+    [ Predicate isNotLatent+    , regex "(d?es[ts]a semana)|agora"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mar(\x00e7|c)o|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDepoisDasTimeofday :: Rule+ruleDepoisDasTimeofday = Rule+  { name = "depois das <time-of-day>"+  , pattern =+    [ regex "(depois|ap(\x00f3|o)s) d?((a|\x00e1|\x00e0)[so]?|os?)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd[/-]mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/\\-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleEmDuration :: Rule+ruleEmDuration = Rule+  { name = "em <duration>"+  , pattern =+    [ regex "em"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "tarde"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "abril|abr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleDimTimeDaManha :: Rule+ruleDimTimeDaManha = Rule+  { name = "<dim time> da manha"+  , pattern =+    [ Predicate $ isGrainFinerThan TG.Year+    , regex "(da|na|pela) manh(\x00e3|a)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let td2 = mkLatent . partOfDay $+                    interval TTime.Open (hour False 4, hour False 12)+        in Token Time <$> intersect td td2+      _ -> Nothing+  }++ruleNCycleProximoqueVem :: Rule+ruleNCycleProximoqueVem = Rule+  { name = "n <cycle> (proximo|que vem)"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "(pr(\x00f3|o)xim(o|a)s?|que vem?|seguintes?)"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMidnight :: Rule+ruleMidnight = Rule+  { name = "midnight"+  , pattern =+    [ regex "meia[\\s\\-]?noite"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "sexta((\\s|\\-)feira)?|sex\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDdddMonthinterval :: Rule+ruleDdddMonthinterval = Rule+  { name = "dd-dd <month>(interval)"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-|a"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       _:+       Token Time td:+       _) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        from <- intersect (dayOfMonth d1) td+        to <- intersect (dayOfMonth d2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleUltimoTime :: Rule+ruleUltimoTime = Rule+  { name = "ultimo <time>"+  , pattern =+    [ regex "(u|\x00fa)ltimo"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "fevereiro|fev\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleNamedmonthnameddayPast :: Rule+ruleNamedmonthnameddayPast = Rule+  { name = "<named-month|named-day> past"+  , pattern =+    [ Predicate isNotLatent+    , regex "(da semana)? passad(o|a)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "inverno"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "ver(\x00e3|a)o"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleRightNow :: Rule+ruleRightNow = Rule+  { name = "right now"+  , pattern =+    [ regex "agora|j(\x00e1|a)|(nesse|neste) instante"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleFazemDuration :: Rule+ruleFazemDuration = Rule+  { name = "fazem <duration>"+  , pattern =+    [ regex "faz(em)?"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleAmanhPelaPartofday :: Rule+ruleAmanhPelaPartofday = Rule+  { name = "amanhã pela <part-of-day>"+  , pattern =+    [ dimension Time+    , regex "(da|na|pela|a)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleHhmmMilitaryTimeofday :: Rule+ruleHhmmMilitaryTimeofday = Rule+  { name = "hhmm (military time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt . mkLatent $ hourMinute False h m+      _ -> Nothing+  }++ruleNamedmonthnameddayNext :: Rule+ruleNamedmonthnameddayNext = Rule+  { name = "<named-month|named-day> next"+  , pattern =+    [ dimension Time+    , regex "(da pr(o|\x00f3)xima semana)|(da semana)? que vem"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTimeofdayPartofday :: Rule+ruleTimeofdayPartofday = Rule+  { name = "<time-of-day> <part-of-day>"+  , pattern =+    [ dimension Time+    , regex "(da|na|pela)"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleDeDatetimeDatetimeInterval :: Rule+ruleDeDatetimeDatetimeInterval = Rule+  { name = "de <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "de?"+    , dimension Time+    , regex "\\-|a"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "junho|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleDentroDeDuration :: Rule+ruleDentroDeDuration = Rule+  { name = "dentro de <duration>"+  , pattern =+    [ regex "(dentro de)|em"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        let from = cycleNth TG.Second 0+            to = inDuration dd+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleSTimeofday :: Rule+ruleSTimeofday = Rule+  { name = "às <time-of-day>"+  , pattern =+    [ regex "(\x00e0|a)s?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "agosto|ago\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleDimTimeDaTarde :: Rule+ruleDimTimeDaTarde = Rule+  { name = "<dim time> da tarde"+  , pattern =+    [ dimension Time+    , regex "(da|na|pela) tarde"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        let td2 = mkLatent . partOfDay $+                    interval TTime.Open (hour False 12, hour False 18)+        in Token Time <$> intersect td td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "final de semana|fim de semana|fds"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleDayofweekSHourmin :: Rule+ruleDayofweekSHourmin = Rule+  { name = "<day-of-week> às <hour-min>"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(\x00e0|a)s"+    , Predicate isNotLatent+    , regex "da|pela"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_:Token Time td3:_) -> do+        td <- intersect td1 td2+        Token Time <$> intersect td td3+      _ -> Nothing+  }++ruleCycleQueVem :: Rule+ruleCycleQueVem = Rule+  { name = "<cycle> (que vem)"+  , pattern =+    [ dimension TimeGrain+    , regex "que vem|seguintes?"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleAnoNovo :: Rule+ruleAnoNovo = Rule+  { name = "ano novo"+  , pattern =+    [ regex "ano novo|reveillon"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "(d[ao]) pr(\x00f3|o)xim[ao]s?|que vem"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleDeYear :: Rule+ruleDeYear = Rule+  { name = "de <year>"+  , pattern =+    [ regex "de|do ano"+    , Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleVesperaDeAnoNovo :: Rule+ruleVesperaDeAnoNovo = Rule+  { name = "vespera de ano novo"+  , pattern =+    [ regex "v(\x00e9|e)spera d[eo] ano[\\s\\-]novo"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleNPassadosCycle :: Rule+ruleNPassadosCycle = Rule+  { name = "n passados <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "passad(a|o)s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleDiaDayofmonthNonOrdinal :: Rule+ruleDiaDayofmonthNonOrdinal = Rule+  { name = "dia <day-of-month> (non ordinal)"+  , pattern =+    [ regex "dia"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayHoras :: Rule+ruleTimeofdayHoras = Rule+  { name = "<time-of-day> horas"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "h\\.?(ora)?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleTwoTimeTokensSeparatedBy :: Rule+ruleTwoTimeTokensSeparatedBy = Rule+  { name = "two time tokens separated by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleTwoTimeTokensSeparatedBy2 :: Rule+ruleTwoTimeTokensSeparatedBy2 = Rule+  { name = "two time tokens separated by \",\"2"+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td2 td1+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "manh(\x00e3|a)"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent .partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "es[ts]a"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "es[ts][ae]"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleProclamaoDaRepblica :: Rule+ruleProclamaoDaRepblica = Rule+  { name = "Proclamação da República"+  , pattern =+    [ regex "proclama(c|\x00e7)(a|\x00e3)o da rep(\x00fa|u)blica"+    ]+  , prod = \_ -> tt $ monthDay 11 15+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ year n+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "ontem"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "outono"+    ]+  , prod = \_ ->+      let from = monthDay 9 23+          to = monthDay 12 21+      in tt $ interval TTime.Open (from, to)+  }++ruleDiaDoTrabalhador :: Rule+ruleDiaDoTrabalhador = Rule+  { name = "Dia do trabalhador"+  , pattern =+    [ regex "dia do trabalh(o|ador)"+    ]+  , prod = \_ -> tt $ monthDay 5 1+  }++ruleNCycleAtras :: Rule+ruleNCycleAtras = Rule+  { name = "n <cycle> atras"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , dimension TimeGrain+    , regex "atr(a|\x00e1)s"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleDayofmonthDeNamedmonth :: Rule+ruleDayofmonthDeNamedmonth = Rule+  { name = "<day-of-month> de <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "de|\\/"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleEntreDatetimeEDatetimeInterval :: Rule+ruleEntreDatetimeEDatetimeInterval = Rule+  { name = "entre <datetime> e <datetime> (interval)"+  , pattern =+    [ regex "entre"+    , dimension Time+    , regex "e"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Open (td1, td2)+      _ -> Nothing+  }++ruleEntreDdEtDdMonthinterval :: Rule+ruleEntreDdEtDdMonthinterval = Rule+  { name = "entre dd et dd <month>(interval)"+  , pattern =+    [ regex "entre"+    , regex "(0?[1-9]|[12]\\d|3[01])"+    , regex "e?"+    , regex "(0?[1-9]|[12]\\d|3[01])"+    , regex "de"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token RegexMatch (GroupMatch (d1:_)):+       _:+       Token RegexMatch (GroupMatch (d2:_)):+       _:+       Token Time td:+       _) -> do+        dd1 <- parseInt d1+        dd2 <- parseInt d2+        dom1 <- intersect (dayOfMonth dd1) td+        dom2 <- intersect (dayOfMonth dd2) td+        tt $ interval TTime.Closed (dom1, dom2)+      _ -> Nothing+  }++ruleCyclePassado :: Rule+ruleCyclePassado = Rule+  { name = "<cycle> passado"+  , pattern =+    [ dimension TimeGrain+    , regex "passad(a|o)s?"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "maio|mai\\.?"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "domingo|dom\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleNossaSenhoraAparecida :: Rule+ruleNossaSenhoraAparecida = Rule+  { name = "Nossa Senhora Aparecida"+  , pattern =+    [ regex "nossa senhora (aparecida)?"+    ]+  , prod = \_ -> tt $ monthDay 10 12+  }++ruleFinados :: Rule+ruleFinados = Rule+  { name = "Finados"+  , pattern =+    [ regex "finados|dia dos mortos"+    ]+  , prod = \_ -> tt $ monthDay 11 2+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "outubro|out\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleAntesDasTimeofday :: Rule+ruleAntesDasTimeofday = Rule+  { name = "antes das <time-of-day>"+  , pattern =+    [ regex "(antes|at(e|\x00e9)|n(a|\x00e3)o mais que) (d?(o|a|\x00e0)s?)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleNProximasCycle :: Rule+ruleNProximasCycle = Rule+  { name = "n proximas <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 2 9999+    , regex "pr(\x00f3|o)xim(o|a)s?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd[/-.]mm[/-.]yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\.\\/\\-](0?[1-9]|1[0-2])[\\.\\/\\-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "novembro|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleIndependecia :: Rule+ruleIndependecia = Rule+  { name = "Independecia"+  , pattern =+    [ regex "independ(\x00ea|e)ncia"+    ]+  , prod = \_ -> tt $ monthDay 9 7+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "quarta((\\s|\\-)feira)?|qua\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "amanh(\x00e3|a)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "setembro|set\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAfternoon+  , ruleAmanhPelaPartofday+  , ruleAnoNovo+  , ruleAntesDasTimeofday+  , ruleDatetimeDatetimeInterval+  , ruleDayOfMonthSt+  , ruleDayofmonthDeNamedmonth+  , ruleDayofweekSHourmin+  , ruleDdddMonthinterval+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDeDatetimeDatetimeInterval+  , ruleDeYear+  , ruleDentroDeDuration+  , ruleDepoisDasTimeofday+  , ruleDiaDayofmonthDeNamedmonth+  , ruleDiaDayofmonthNonOrdinal+  , ruleDiaDoTrabalhador+  , ruleDimTimeDaMadrugada+  , ruleDimTimeDaManha+  , ruleDimTimeDaTarde+  , ruleEmDuration+  , ruleEntreDatetimeEDatetimeInterval+  , ruleEntreDdEtDdMonthinterval+  , ruleEsteCycle+  , ruleEvening+  , ruleFazemDuration+  , ruleFinados+  , ruleHhhmmTimeofday+  , ruleHhmmMilitaryTimeofday+  , ruleHourofdayAndRelativeMinutes+  , ruleHourofdayAndRelativeMinutes2+  , ruleHourofdayAndQuarter+  , ruleHourofdayAndThreeQuarter+  , ruleHourofdayAndHalf+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayIntegerAsRelativeMinutes2+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleHourofdayThreeQuarter+  , ruleInThePartofday+  , ruleIndependecia+  , ruleIntegerParaAsHourofdayAsRelativeMinutes+  , ruleIntegerParaAsHourofdayAsRelativeMinutes2+  , ruleHalfParaAsHourofdayAsRelativeMinutes+  , ruleQuarterParaAsHourofdayAsRelativeMinutes+  , ruleThreeQuarterParaAsHourofdayAsRelativeMinutes+  , ruleIntersect+  , ruleIntersectByDaOrDe+  , ruleLastTime+  , ruleMidnight+  , ruleMorning+  , ruleNCycleAtras+  , ruleNCycleProximoqueVem+  , ruleNPassadosCycle+  , ruleNProximasCycle+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthnameddayNext+  , ruleNamedmonthnameddayPast+  , ruleNaoDate+  , ruleNatal+  , ruleNextTime+  , ruleCycleQueVem+  , ruleProximoCycle+  , ruleNoon+  , ruleNossaSenhoraAparecida+  , ruleNow+  , ruleCycleAntesDeTime+  , ruleCyclePassado+  , rulePartofdayDessaSemana+  , rulePassadosNCycle+  , ruleProclamaoDaRepblica+  , ruleProximasNCycle+  , ruleRightNow+  , ruleSHourminTimeofday+  , ruleSHourmintimeofday+  , ruleSTimeofday+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeofdayAmpm+  , ruleTimeofdayHoras+  , ruleTimeofdayLatent+  , ruleTimeofdayPartofday+  , ruleTiradentes+  , ruleTomorrow+  , ruleTwoTimeTokensSeparatedBy+  , ruleTwoTimeTokensSeparatedBy2+  , ruleUltimoTime+  , ruleVesperaDeAnoNovo+  , ruleWeekend+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleTimezone+  ]
+ Duckling/Time/RO/Corpus.hs view
@@ -0,0 +1,91 @@+-- 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.Time.RO.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = RO}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "acum"+             , "chiar acum"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "azi"+             , "astazi"+             , "astăzi"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "ieri"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "maine"+             , "mâine"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "luni"+             , "lunea asta"+             , "lunea aceasta"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Luni, 18 Feb"+             , "Luni, 18 Februarie"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "marti"+             , "marți"+             , "Marti 19"+             , "Marti pe 19"+             , "Marți 19"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "joi"+             , "jo"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "vineri"+             , "vi"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "sambata"+             , "sâmbătă"+             , "sam"+             , "sa"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "duminica"+             , "duminică"+             , "du"+             , "dum"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "1 martie"+             , "intai martie"+             ]+  , examples (datetimeInterval ((2013, 6, 19, 0, 0, 0), (2013, 6, 21, 0, 0, 0)) Day)+             [ "iunie 19-20"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "ziua de craciun"+             , "crăciun"+             ]+  ]
+ Duckling/Time/RO/Rules.hs view
@@ -0,0 +1,1503 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.RO.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleAcum :: Rule+ruleAcum = Rule+  { name = "acum"+  , pattern =+    [ regex "(chiar)? ?acum|imediat"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "lu(n(ea|i)?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleDupamiaza :: Rule+ruleDupamiaza = Rule+  { name = "dupamiaza"+  , pattern =+    [ regex "dupamiaz(a|\x0103)|dup(a|\x0103) amiaz(a|\x0103)"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 12, hour False 19)+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "dec(embrie)?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "ma(r((t|\x021b)(ea|i))?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "sf\\.?((a|\x00e2)ntul)? Valentin"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleSinceTimeofday :: Rule+ruleSinceTimeofday = Rule+  { name = "since <time-of-day>"+  , pattern =+    [ regex "de|din"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "(siua de )? an(ul)? nou"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s(a|\x00e2)mb(a|\x0103)t(a|\x0103)|s(a|\x00e2)m|s(a|\x00e2)"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "iul(ie)?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleOrdinalTrimestruYear :: Rule+ruleOrdinalTrimestruYear = Rule+  { name = "<ordinal> trimestru <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (n - 1) td+      _ -> Nothing+  }++ruleInNamedmonth :: Rule+ruleInNamedmonth = Rule+  { name = "in <named-month>"+  , pattern =+    [ regex "(i|\x00ee)n"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "ultim(ul|a)"+    , dimension TimeGrain+    , regex "din"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleIntroNamedday :: Rule+ruleIntroNamedday = Rule+  { name = "intr-o <named-day>"+  , pattern =+    [ regex "((i|\x00ee)n(tr)?(\\-?o)?)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ Predicate isAMonth+    , regex "(3[01]|[12]\\d|0?[1-9])"+    , regex "\\-"+    , regex "(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       _) -> do+        d1 <- parseInt m1+        d2 <- parseInt m2+        dom1 <- intersect (dayOfMonth d1) td+        dom2 <- intersect (dayOfMonth d2) td+        tt $ interval TTime.Closed (dom1, dom2)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "jo(ia?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "(i|\x00ee)n"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt $ inDuration dd+      _ -> Nothing+  }++ruleIeri :: Rule+ruleIeri = Rule+  { name = "ieri"+  , pattern =+    [ regex "ieri"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleCycleAcesta :: Rule+ruleCycleAcesta = Rule+  { name = "<cycle> acesta"+  , pattern =+    [ regex "aceasta|acest|(a|\x0103)sta"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleAzi :: Rule+ruleAzi = Rule+  { name = "azi"+  , pattern =+    [ regex "a(st(a|\x0103))?zi"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "noon"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleTimeTrecuta :: Rule+ruleTimeTrecuta = Rule+  { name = "<time> trecut[aă]?"+  , pattern =+    [ dimension Time+    , regex "(trecut(a|\x0103)?)"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "aceasta|(a|\x0103)sta|urm(a|\x0103)toare"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "(i|\x00ee)ntre"+    , Predicate isATimeOfDay+    , regex "(s|\x0219)i"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "ian(uarie)?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleUrmatoareaCycle :: Rule+ruleUrmatoareaCycle = Rule+  { name = "urmatoarea <cycle>"+  , pattern =+    [ regex "(urm(a|\x0103)to(area|rul)|viito(are|r))"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleCycleAcesta2 :: Rule+ruleCycleAcesta2 = Rule+  { name = "<cycle> acesta"+  , pattern =+    [ dimension TimeGrain+    , regex "aceasta|acest|(a|\x0103)sta|curent(a|\x0103)"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "martie|mar"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleCraciun :: Rule+ruleCraciun = Rule+  { name = "craciun"+  , pattern =+    [ regex "(ziua de )?cr(a|\x0103)ciun"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleTrimestruNumeralYear :: Rule+ruleTrimestruNumeralYear = Rule+  { name = "trimestru <number> <year>"+  , pattern =+    [ Predicate $ isGrain TG.Quarter+    , dimension Numeral+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token Time td:_) -> do+        v <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (v - 1) td+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])/(0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleLaTimeofday :: Rule+ruleLaTimeofday = Rule+  { name = "la <time-of-day>"+  , pattern =+    [ regex "la|@ (ora)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "apr(ilie)?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleBlackFriday :: Rule+ruleBlackFriday = Rule+  { name = "black friday"+  , pattern =+    [ regex "black frid?day"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 4 5 11+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "ajun(ul)? (de )?cr(a|\x0103)ciun"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++rulePentruDuration :: Rule+rulePentruDuration = Rule+  { name = "pentru <duration>"+  , pattern =+    [ regex "pentru"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) -> tt $ inDuration dd+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdaySfert :: Rule+ruleHourofdaySfert = Rule+  { name = "<hour-of-day> sfert"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "((s|\x0219)i )?(un )?sfert"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 15+      _ -> Nothing+  }++ruleHourofdayJumatate :: Rule+ruleHourofdayJumatate = Rule+  { name = "<hour-of-day> sfert"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "((s|\x0219)i )?jum(a|\x0103)tate|jumate"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       _) -> tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "vi(n(er(ea|i))?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDiseara :: Rule+ruleDiseara = Rule+  { name = "diseara"+  , pattern =+    [ regex "disear(a|\x0103)|((i|\x00ee)n aceas(a|\x0103) )?sear(a|\x0103)"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleDayofmonthNumeral :: Rule+ruleDayofmonthNumeral = Rule+  { name = "<day-of-month> (number)"+  , pattern =+    [ Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "dup(a|\x0103)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td1:_:Token Time td2:_) -> do+        v <- getIntValue token+        tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(dup(a|\x0103)|(i|\x00ee)ncep(a|\x00e2)nd cu)"+    , Predicate isATimeOfDay+    , regex "(dar |(s|\x0219)i )?((i|\x00ee)nainte|p(a|\x00e2)n(a|\x0103) la( de)?)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "feb(ruarie)?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "primavar(a|\x0103)"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 3 20, monthDay 6 21)+  }++ruleUrmatoareleNCycle :: Rule+ruleUrmatoareleNCycle = Rule+  { name = "urmatoarele n <cycle>"+  , pattern =+    [ regex "urm(a|\x0103)to(arele|rii|area)"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "toamn(a|\x0103)"+    ]+  , prod = \_ -> tt $+      interval TTime.Open (monthDay 9 23, monthDay 12 21)+  }++ruleDupaDuration :: Rule+ruleDupaDuration = Rule+  { name = "dupa <duration>"+  , pattern =+    [ regex "dup(a|\x0103)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "(ajun(ul)? )?(de )?an(ul)? nou"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "p(a|\x00ee)n(a|\x0103) ((i|\x00ee)n|la)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleNameddayPeDayofmonthNumeral :: Rule+ruleNameddayPeDayofmonthNumeral = Rule+  { name = "<named-day> pe <day-of-month> (number)"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "pe"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(cam|aproximativ|(i|\x00ee)n jur de)"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "p(a|\x00ee)n(a|\x0103) ((i|\x00ee)n|la)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleDayofmonthnumberNamedmonth :: Rule+ruleDayofmonthnumberNamedmonth = Rule+  { name = "<day-of-month>(number) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "iun(ie)?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleIntreDatetimeSiDatetimeInterval :: Rule+ruleIntreDatetimeSiDatetimeInterval = Rule+  { name = "intre <datetime> si <datetime> (interval)"+  , pattern =+    [ regex "(i|\x00ee)nre"+    , dimension Time+    , regex "(s|\x0219)i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "din"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td1:_:Token Time td2:_) -> do+        v <- getIntValue token+        Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "aug(ust)?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "(week(\\s|\\-)?end|wkend)"+    ]+  , prod = \_ -> do+      fri <- intersect (dayOfWeek 5) (hour False 18)+      mon <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (fri, mon)+  }++rulePeDayofmonthNonOrdinal :: Rule+rulePeDayofmonthNonOrdinal = Rule+  { name = "pe <day-of-month> (non ordinal)"+  , pattern =+    [ regex "pe"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleTimeAceastaacestaasta :: Rule+ruleTimeAceastaacestaasta = Rule+  { name = "<time> (aceasta|acesta|[aă]sta)"+  , pattern =+    [ dimension Time+    , regex "aceasta|(a|\x0103)sta|urm(a|\x0103)toare"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "sf(a|\x00e2)r(s|\x0219)itul lunii"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++rulePartofdayAsta :: Rule+rulePartofdayAsta = Rule+  { name = "<part-of-day> asta"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "asta"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleUltimaCycle :: Rule+ruleUltimaCycle = Rule+  { name = "ultima <cycle>"+  , pattern =+    [ regex "ultim(a|ul)"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleCycleUrmatoare :: Rule+ruleCycleUrmatoare = Rule+  { name = "<cycle> urmatoare"+  , pattern =+    [ dimension TimeGrain+    , regex "(urm(a|\x0103)to(are|r)|viito(are|r))"+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleTheDayofmonthNumeral :: Rule+ruleTheDayofmonthNumeral = Rule+  { name = "the <day-of-month> (number)"+  , pattern =+    [ regex "pe"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ dayOfMonth v+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleCycleTrecut :: Rule+ruleCycleTrecut = Rule+  { name = "<cycle> trecut"+  , pattern =+    [ dimension TimeGrain+    , regex "trecut(a|\x0103)?"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDayofmonthNumeralOfNamedmonth :: Rule+ruleDayofmonthNumeralOfNamedmonth = Rule+  { name = "<day-of-month> (number) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "din"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDurationInainteDeTime :: Rule+ruleDurationInainteDeTime = Rule+  { name = "<duration> inainte de <time>"+  , pattern =+    [ dimension Duration+    , regex "(i|\x00ee)nainte de"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "din"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDurationInUrma :: Rule+ruleDurationInUrma = Rule+  { name = "<duration> in urma"+  , pattern =+    [ dimension Duration+    , regex "(i|\x00ee)n urm(a|\x0103)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) -> tt $ durationAgo dd+      _ -> Nothing+  }++ruleDurationDeAcum :: Rule+ruleDurationDeAcum = Rule+  { name = "<duration> de acum"+  , pattern =+    [ dimension Duration+    , regex "de (acum|azi)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) -> tt $ inDuration dd+      _ -> Nothing+  }++ruleSezonAnotimp :: Rule+ruleSezonAnotimp = Rule+  { name = "sezon anotimp"+  , pattern =+    [ regex "var(a|\x0103)"+    ]+  , prod = \_ ->+      tt $ interval TTime.Open (monthDay 6 21, monthDay 9 23)+  }++ruleSearaNoapte :: Rule+ruleSearaNoapte = Rule+  { name = "sear[aă] noapte"+  , pattern =+    [ regex "sear(a|\x0103)|noapte"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 18, hour False 0)+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "iarn(a|\x0103)"+    ]+  , prod = \_ ->+      tt $ interval TTime.Open (monthDay 12 21, monthDay 3 20)+  }++ruleUltimeleNCycle :: Rule+ruleUltimeleNCycle = Rule+  { name = "ultimele n <cycle>"+  , pattern =+    [ regex "ultim(ele|ii|a)"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "dup(a|\x0103)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ withDirection TTime.After td+      _ -> Nothing+  }++ruleDimineata :: Rule+ruleDimineata = Rule+  { name = "diminea[tț][aă]"+  , pattern =+    [ regex "diminea(t|\x021b)(a|\x0103)"+    ]+  , prod = \_ -> tt . mkLatent . partOfDay $+      interval TTime.Open (hour False 4, hour False 12)+  }++ruleTimeUrmatoarer :: Rule+ruleTimeUrmatoarer = Rule+  { name = "<time> urm[aă]to(are|r)"+  , pattern =+    [ regex "urm(a|\x0103)to(are|r)"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mai"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleTimeofdayFix :: Rule+ruleTimeofdayFix = Rule+  { name = "<time-of-day> fix"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(fix|exact)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "du(m(inic(a|\x0103))?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleMaine :: Rule+ruleMaine = Rule+  { name = "maine"+  , pattern =+    [ regex "m(a|\x00e2)ine"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "oct(ombrie)?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleHalloweenDay :: Rule+ruleHalloweenDay = Rule+  { name = "halloween day"+  , pattern =+    [ regex "hall?owe?en"+    ]+  , prod = \_ -> tt $ monthDay 10 31+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++rulePeDate :: Rule+rulePeDate = Rule+  { name = "pe <date>"+  , pattern =+    [ regex "pe"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleDayofmonthnumberNamedmonthYear :: Rule+ruleDayofmonthnumberNamedmonthYear = Rule+  { name = "<day-of-month>(number) <named-month> year"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+        v <- parseInt match+        dom <- intersectDOM td token+        Token Time <$> intersect dom (year v)+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "ultima"+    , Predicate isADayOfWeek+    , regex "din"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleOrdinalTrimestru :: Rule+ruleOrdinalTrimestru = Rule+  { name = "<ordinal> trimestru"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleByTime :: Rule+ruleByTime = Rule+  { name = "by <time>"+  , pattern =+    [ regex "p(a|\x00e2)n(a|\x0103) (la|(i|\x00ee)n)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $+        interval TTime.Open (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[-/](0?[1-9]|1[0-2])[/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "noi(embrie)?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "mi(e(rcur(ea|i))?)?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])[-/](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "sf(a|\x00e2)r(s|\x0219)itul anului"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleMothersDay :: Rule+ruleMothersDay = Rule+  { name = "Mother's Day"+  , pattern =+    [ regex "ziua (mamei|memeii)"+    ]+  , prod = \_ -> tt $ nthDOWOfMonth 1 7 5+  }++ruleNameddayDayofmonthNumeral :: Rule+ruleNameddayDayofmonthNumeral = Rule+  { name = "<named-day> <day-of-month> (number)"+  , pattern =+    [ Predicate isADayOfWeek+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "sept(embrie)?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAcum+  , ruleAfterTimeofday+  , ruleAzi+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleBlackFriday+  , ruleByTheEndOfTime+  , ruleByTime+  , ruleChristmasEve+  , ruleCraciun+  , ruleCycleAcesta+  , ruleCycleAcesta2+  , ruleCycleTrecut+  , ruleCycleUrmatoare+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthNumeral+  , ruleDayofmonthNumeralOfNamedmonth+  , ruleDayofmonthnumberNamedmonth+  , ruleDayofmonthnumberNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDimineata+  , ruleDiseara+  , ruleDupaDuration+  , ruleDupamiaza+  , ruleDurationDeAcum+  , ruleDurationInUrma+  , ruleDurationInainteDeTime+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHalloweenDay+  , ruleHhmm+  , ruleHhmmss+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayJumatate+  , ruleHourofdaySfert+  , ruleIeri+  , ruleInDuration+  , ruleInNamedmonth+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntreDatetimeSiDatetimeInterval+  , ruleIntroNamedday+  , ruleLaTimeofday+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleMaine+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMonthDdddInterval+  , ruleMothersDay+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNameddayDayofmonthNumeral+  , ruleNameddayPeDayofmonthNumeral+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNoon+  , ruleNthTimeAfterTime+  , ruleNthTimeOfTime+  , ruleOrdinalTrimestru+  , ruleOrdinalTrimestruYear+  , rulePartofdayAsta+  , rulePeDate+  , rulePeDayofmonthNonOrdinal+  , rulePentruDuration+  , ruleSearaNoapte+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSezonAnotimp+  , ruleSinceTimeofday+  , ruleTheDayofmonthNumeral+  , ruleThisnextDayofweek+  , ruleTimeAceastaacestaasta+  , ruleTimePartofday+  , ruleTimezone+  , ruleTimeTrecuta+  , ruleTimeUrmatoarer+  , ruleTimeofdayFix+  , ruleTimeofdayLatent+  , ruleTrimestruNumeralYear+  , ruleUltimaCycle+  , ruleUltimeleNCycle+  , ruleUntilTimeofday+  , ruleUrmatoareaCycle+  , ruleUrmatoareleNCycle+  , ruleValentinesDay+  , ruleWeekend+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYyyymmdd+  ]
+ Duckling/Time/SV/Corpus.hs view
@@ -0,0 +1,615 @@+-- 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.Time.SV.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = SV}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "nu"+             , "just nu"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "idag"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "igår"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "imorgon"+             , "i morgon"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "måndag"+             , "mån"+             , "på måndag"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Måndag den 18 februari"+             , "Mån, 18 februari"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "tisdag"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "torsdag"+             , "tors"+             , "tors."+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "fredag"+             , "fre"+             , "fre."+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "lördag"+             , "lör"+             , "lör."+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "söndag"+             , "sön"+             , "sön."+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "Den förste mars"+             , "Den första mars"+             , "1. mars"+             , "Den 1. mars"+             ]+  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)+             [ "3 mars"+             , "den tredje mars"+             , "den 3. mars"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "3 mars 2015"+             , "tredje mars 2015"+             , "3. mars 2015"+             , "3-3-2015"+             , "03-03-2015"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "På den 15."+             , "På den 15"+             , "Den 15."+             , "Den 15"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "den 15. februari"+             , "15. februari"+             , "februari 15"+             , "15-02"+             , "15/02"+             ]+  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)+             [ "8 Aug"+             ]+  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)+             [ "Oktober 2014"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "31/10/1974"+             , "31/10/74"+             , "31-10-74"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "14april 2015"+             , "April 14, 2015"+             , "fjortonde April 15"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "nästa fredag igen"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nästa mars"+             ]+  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)+             [ "nästa mars igen"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "Söndag, 10 feb"+             , "Söndag 10 Feb"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "Ons, Feb13"+             , "Ons feb13"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "Måndag, Feb 18"+             , "Mån, februari 18"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "denna vecka"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "förra vecka"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "nästa vecka"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "förra månad"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "nästa månad"+             ]+  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)+             [ "detta kvartal"+             ]+  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)+             [ "nästa kvartal"+             ]+  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)+             [ "tredje kvartalet"+             , "3. kvartal"+             , "3 kvartal"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "4. kvartal 2018"+             , "fjärde kvartalet 2018"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "förra år"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "i fjol"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "i år"+             , "detta år"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "nästa år"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "förra söndag"+             , "söndag i förra veckan"+             , "söndag förra veckan"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "förra tisdag"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "nästa tisdag"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "nästa onsdag"+             ]+  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)+             [ "onsdag i nästa vecka"+             , "onsdag nästa vecka"+             , "nästa onsdag igen"+             ]+  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)+             [ "nästa fredag igen"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "måndag denna veckan"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "tisdag denna vecka"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "onsdag denna vecka"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "i överimorgon"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "i förrgår"+             ]+  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)+             [ "sista måndag i mars"+             ]+  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)+             [ "sista söndag i mars 2014"+             ]+  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)+             [ "tredje dagen i oktober"+             , "tredje dagen i Oktober"+             ]+  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)+             [ "första veckan i oktober 2014"+             , "första veckan i Oktober 2014"+             ]+  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)+             [ "sista dagen i oktober 2015"+             , "sista dagen i Oktober 2015"+             ]+  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)+             [ "sista veckan i september 2014"+             , "sista veckan i September 2014"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "första tisdag i oktober"+             , "första tisdagen i Oktober"+             ]+  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)+             [ "tredje tisdagen i september 2014"+             , "tredje tisdagen i September 2014"+             ]+  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)+             [ "första onsdagen i oktober 2014"+             , "första onsdagen i Oktober 2014"+             ]+  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)+             [ "andra onsdagen i oktober 2014"+             , "andra onsdagen i Oktober 2014"+             ]+  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)+             [ "klockan 3"+             , "kl. 3"+             ]+  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)+             [ "3:18"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "klockan 15"+             , "kl. 15"+             , "15h"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "ca. kl. 15"+             , "cirka kl. 15"+             , "omkring klockan 15"+             ]+  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)+             [ "imorgon klockan 17 exakt"+             , "imorgon kl. 17 precis"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "kvart över 15"+             , "15:15"+             ]+  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)+             [ "kl. 20 över 15"+             , "klockan 20 över 15"+             , "tjugo över 15"+             , "kl. 15:20"+             , "15:20"+             ]+  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)+             [ "15:30"+             ]+  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)+             [ "kvart i 12"+             , "kvart i tolv"+             , "11:45"+             ]+  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)+             [ "klockan 9 på lördag"+             ]+  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)+             [ "Fre, Jul 18, 2014 19:00"+             ]+  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)+             [ "Fre, Jul 18"+             , "Jul 18, Fre"+             ]+  , examples (datetime (2014, 9, 20, 19, 30, 0) Minute)+             [ "kl. 19:30, Lör, 20 sep"+             ]+  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)+             [ "om 1 sekund"+             , "om en sekund"+             , "en sekund från nu"+             ]+  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)+             [ "om 1 minut"+             , "om en minut"+             ]+  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)+             [ "om 2 minuter"+             , "om två minuter"+             , "om 2 minuter mer"+             , "om två minuter mer"+             --, "2 minuter från nu" t14892978+             , "två minuter från nu"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)+             [ "om 60 minuter"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om en halv timme"+             ]+  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)+             [ "om 2,5 timme"+             , "om 2 och en halv timme"+             , "om två och en halv timme"+             ]+  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)+             [ "om en timme"+             , "om 1 timme"+             , "om 1t"+             ]+  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)+             [ "om ett par timmar"+             ]+  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)+             [ "om 24 timmar"+             ]+  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)+             [ "om en dag"+             ]+  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)+             [ -- "3 år från idag" t14892978+             ]+  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)+             [ "om 7 dagar"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "om en vecka"+             ]+  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)+             [ "om ca. en halv timme"+             , "om cirka en halv timme"+             ]+  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)+             [ "7 dagar sedan"+             , "sju dagar sedan"+             ]+  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)+             [ "14 dagar sedan"+             , "fjorton dagar sedan"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "en vecka sedan"+             , "1 vecka sedan"+             ]+  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)+             [ "3 veckor sedan"+             , "tre veckor sedan"+             ]+  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)+             [ "3 månader sedan"+             , "tre månader sedan"+             ]+  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)+             [ "två år sedan"+             , "2 år sedan"+             ]+  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)+             [ "1954"+             ]+  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)+             [ "denna sommaren"+             , "den här sommaren"+             ]+  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)+             [ "denna vintern"+             , "den här vintern"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "juldagen"+             ]+  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)+             [ "nyårsafton"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "nyårsdagen"+             , "nyårsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)+             [ "ikväll"+             ]+  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)+             [ "förra helg"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)+             [ "imorgon kväll"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)+             [ "imorgon lunch"+             ]+  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)+             [ "igår kväll"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "denna helgen"+             , "denna helg"+             , "i helgen"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "måndag morgon"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "senaste 2 sekunder"+             , "senaste två sekunderna"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "nästa 3 sekunder"+             , "nästa tre sekunder"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "senaste 2 minuter"+             , "senaste två minuter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "nästa 3 minuter"+             , "nästa tre minuter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "senaste 1 timme"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "nästa 3 timmar"+             , "nästa tre timmar"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "senaste 2 dagar"+             , "senaste två dagar"+             , "senaste 2 dagar"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "nästa 3 dagar"+             , "nästa tre dagar"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "senaste 2 veckor"+             , "senaste två veckorna"+             , "senaste två veckor"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "nästa 3 veckor"+             , "nästa tre veckorna"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "senaste 2 månader"+             , "senaste två månader"+             , "senaste två månader"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "nästa 3 månader"+             , "nästa tre månader"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "senaste 2 år"+             , "senaste två år"+             , "senaste 2 år"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "nästa 3 år"+             , "nästa tre år"+             ]+  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)+             [ "13-15 juli"+             , "13-15 Juli"+             , "13 till 15 Juli"+             , "13 juli till 15 juli"+             ]+  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)+             [ "8 Aug - 12 Aug"+             , "8 Aug - 12 aug"+             , "8 aug - 12 aug"+             , "8 augusti - 12 augusti"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)+             [ "9:30 - 11:00"+             , "9:30 till 11:00"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)+             [ "från 9:30 - 11:00 på torsdag"+             , "från 9:30 till 11:00 på torsdag"+             , "mellan 9:30 och 11:00 på torsdag"+             , "9:30 - 11:00 på torsdag"+             , "9:30 till 11:00 på torsdag"+             , "efter 9:30 men före 11:00 på torsdag"+             , "torsdag från 9:30 till 11:00"+             , "torsdag mellan 9:30 och 11:00"+             , "från 9:30 till 11:00 på torsdag"+             ]+  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)+             [ "torsdag från 9 till 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)+             [ "11:30-13:30"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)+             [ "inom 2 veckor"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)+             [ "innan kl. 14"+             , "innan klockan 14"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "@ 16 CET"+             , "kl. 16 CET"+             , "klockan 16 CET"+             ]+  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)+             [ "torsdag kl. 8:00 GMT"+             , "torsdag klockan 8:00 GMT"+             , "torsdag 08:00 GMT"+             ]+  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)+             [ "idag kl. 14"+             , "idag klockan 14"+             , "kl. 14"+             , "klockan 14"+             ]+  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)+             [ "25/4 kl. 16:00"+             , "25/4 klockan 16:00"+             , "25-04 klockan 16:00"+             , "25-4 kl. 16:00"+             ]+  , examples (datetime (2013, 2, 13, 15, 0, 0) Minute)+             [ "15:00 imorgon"+             , "kl. 15:00 imorgon"+             , "klockan 15:00 imorgon"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)+             [ "efter kl. 14"+             , "efter klockan 14"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)+             [ "efter 5 dagar"+             , "efter fem dagar"+             ]+  , examples (datetime (2013, 2, 17, 4, 0, 0) Hour)+             [ "om 5 dagar"+             , "om fem dagar"+             ]+  , examples (datetimeOpenInterval After (2013, 2, 13, 14, 0, 0) Hour)+             [ "efter imorgon kl. 14"+             , "efter imorgon klockan 14"+             , "imorgon efter kl. 14"+             , "imorgon efter klockan 14"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)+             [ "före kl. 11"+             , "före klockan 11"+             ]+  , examples (datetimeOpenInterval Before (2013, 2, 13, 11, 0, 0) Hour)+             [ "imorgon före kl. 11"+             , "imorgon före klockan 11"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)+             [ "under eftermiddagen"+             ]+  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)+             [ "kl. 13:30"+             , "klockan 13:30"+             ]+  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)+             [ "om 15 minuter"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)+             [ "efter lunch"+             ]+  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "nästa måndag"+             ]+  ]
+ Duckling/Time/SV/Rules.hs view
@@ -0,0 +1,1923 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.SV.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Ordinal.Types (OrdinalData (..))+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "m\x00e5ndag(en)?|m\x00e5n\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "i \x00f6verimorgon"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "december|dec\\.?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 59+    , regex "\x00f6ver"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (token:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleHourofdayIntegerAsRelativeMinutes :: Rule+ruleHourofdayIntegerAsRelativeMinutes = Rule+  { name = "<hour-of-day> <integer> (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "(en)? ?(kvart)(er)?"+    , regex "i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }++ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "(en)? ?(kvart)(er)?"+    , regex "\x00f6ver"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "<hour-of-day> quarter (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex  "(en)? ?(kvart)(er)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ regex "halvtimme"+    , regex "i"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:_:Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }++ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ regex "halvtimme"+    , regex "\x00f6ver"+    , Predicate isAnHourOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:+       _:+       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "<hour-of-day> half (as relative minutes)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "halvtimme"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "tisdag(en)?|tis?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleTheOrdinalCycleOfTime :: Rule+ruleTheOrdinalCycleOfTime = Rule+  { name = "the <ordinal> <cycle> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "av|i|fr\x00e5n"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "ny\x00e5rsdag(en)?"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "(sista|f\x00f6rra|senaste)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "l\x00f6rdag(en)?|l\x00f6r\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleDatetimeDatetimeInterval :: Rule+ruleDatetimeDatetimeInterval = Rule+  { name = "<datetime> - <datetime> (interval)"+  , pattern =+    [ Predicate isNotLatent+    , regex "\\-|till|till och med|tom"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juli|jul\\.?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleEvening :: Rule+ruleEvening = Rule+  { name = "evening"+  , pattern =+    [ regex "kv\x00e4ll(en)?"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleTheDayofmonthNonOrdinal :: Rule+ruleTheDayofmonthNonOrdinal = Rule+  { name = "the <day-of-month> (non ordinal)"+  , pattern =+    [ regex "den"+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleCycleAfterTime :: Rule+ruleCycleAfterTime = Rule+  { name = "<cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "om"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "just nu|nu|(i )?detta \x00f6gonblick"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleLastCycleOfTime :: Rule+ruleLastCycleOfTime = Rule+  { name = "last <cycle> of <time>"+  , pattern =+    [ regex "sista"+    , dimension TimeGrain+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleFromDatetimeDatetimeInterval :: Rule+ruleFromDatetimeDatetimeInterval = Rule+  { name = "from <datetime> - <datetime> (interval)"+  , pattern =+    [ regex "fr\x00e5n"+    , dimension Time+    , regex "\\-|till|till och med|tom"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleMonthDdddInterval :: Rule+ruleMonthDdddInterval = Rule+  { name = "<month> dd-dd (interval)"+  , pattern =+    [ regex "([012]?\\d|30|31)(er|\\.)?"+    , regex "\\-|till"+    , regex "([012]?\\d|30|31)(er|\\.)?"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:_)):+       _:+       Token RegexMatch (GroupMatch (m2:_)):+       Token Time td:+       _) -> do+        v1 <- parseInt m1+        v2 <- parseInt m2+        from <- intersect (dayOfMonth v1) td+        to <- intersect (dayOfMonth v2) td+        tt $ interval TTime.Closed (from, to)+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "torsdag(en)?|tors?\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|na|et)? efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|na|et)? f\x00f6re"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleYearLatent2 :: Rule+ruleYearLatent2 = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 2101 10000+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleTimeAfterNext :: Rule+ruleTimeAfterNext = Rule+  { name = "<time> after next"+  , pattern =+    [ regex "n\x00e4sta"+    , dimension Time+    , regex "igen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 True td+      _ -> Nothing+  }++ruleTheIdesOfNamedmonth :: Rule+ruleTheIdesOfNamedmonth = Rule+  { name = "the ides of <named-month>"+  , pattern =+    [ regex "mitten av"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->+        Token Time <$>+          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "middag|(kl(\\.|ockan)?)? tolv"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "i dag|idag"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "(kommande|n\x00e4sta)"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "i f\x00f6rrg\x00e5r"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleBetweenTimeofdayAndTimeofdayInterval :: Rule+ruleBetweenTimeofdayAndTimeofdayInterval = Rule+  { name = "between <time-of-day> and <time-of-day> (interval)"+  , pattern =+    [ regex "mellan"+    , Predicate isATimeOfDay+    , regex "och"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "n\x00e4sta|kommande"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "januari|jan\\.?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTheCycleOfTime :: Rule+ruleTheCycleOfTime = Rule+  { name = "the <cycle> of <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "(en|na|et)? av"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain 0 td+      _ -> Nothing+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(cirka|ca\\.|-?ish)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleOnDate :: Rule+ruleOnDate = Rule+  { name = "on <date>"+  , pattern =+    [ regex "den|p\x00e5|under"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "mars|mar\\.?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "fr\x00e5n (idag|nu)"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "lunch(en)?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 14+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "sista|senaste|f\x00f6rra"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        d <- parseInt m1+        m <- parseInt m2+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "eftermiddag(en)?"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "april|apr\\.?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleTimeBeforeLast :: Rule+ruleTimeBeforeLast = Rule+  { name = "<time> before last"+  , pattern =+    [ regex "sista"+    , dimension Time+    , regex "igen"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-2) False td+      _ -> Nothing+  }++ruleNamedmonthDayofmonthOrdinal :: Rule+ruleNamedmonthDayofmonthOrdinal = Rule+  { name = "<named-month> <day-of-month> (ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleChristmasEve :: Rule+ruleChristmasEve = Rule+  { name = "christmas eve"+  , pattern =+    [ regex "julafton?"+    ]+  , prod = \_ -> tt $ monthDay 12 24+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "fredag(en)?|fre\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleDayofmonthordinalNamedmonth :: Rule+ruleDayofmonthordinalNamedmonth = Rule+  { name = "<day-of-month>(ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNthTimeAfterTime :: Rule+ruleNthTimeAfterTime = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleAfterDuration :: Rule+ruleAfterDuration = Rule+  { name = "after <duration>"+  , pattern =+    [ regex "efter"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt . withDirection TTime.After $ inDuration dd+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour False n+      _ -> Nothing+  }++ruleDayofmonthOrdinalOfNamedmonth :: Rule+ruleDayofmonthOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMOrdinal+    , regex "av|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleFromTimeofdayTimeofdayInterval :: Rule+ruleFromTimeofdayTimeofdayInterval = Rule+  { name = "from <time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ regex "(efter|fr\x00e5n)"+    , Predicate isATimeOfDay+    , regex "((men )?f\x00f6re)|\\-|till|till och med|tom"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "februari|feb\\.?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "(precis|exakt)( kl.| klockan)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleInduringThePartofday2 :: Rule+ruleInduringThePartofday2 = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ regex "om|i"+    , Predicate isAPartOfDay+    , regex "en|ten"+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "sommar(en)"+    ]+  , prod = \_ ->+      let from = monthDay 6 21+          to = monthDay 9 23+      in tt $ interval TTime.Open (from, to)+  }++ruleBetweenDatetimeAndDatetimeInterval :: Rule+ruleBetweenDatetimeAndDatetimeInterval = Rule+  { name = "between <datetime> and <datetime> (interval)"+  , pattern =+    [ regex "mellan"+    , dimension Time+    , regex "och"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNewYearsEve :: Rule+ruleNewYearsEve = Rule+  { name = "new year's eve"+  , pattern =+    [ regex "ny\x00e5rsafton?"+    ]+  , prod = \_ -> tt $ monthDay 12 31+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "sedan"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleByTheEndOfTime :: Rule+ruleByTheEndOfTime = Rule+  { name = "by the end of <time>"+  , pattern =+    [ regex "i slutet av"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ interval TTime.Closed (cycleNth TG.Second 0, td)+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "efter jobbet"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 17, hour False 21)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "sista|senaste|f\x00f6rra"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(sharp|precis|exakt)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleWithinDuration :: Rule+ruleWithinDuration = Rule+  { name = "within <duration>"+  , pattern =+    [ regex "(innanf\x00f6r|inom)"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        let from = cycleNth TG.Second 0+            to = inDuration dd+        in tt $ interval TTime.Open (from, to)+      _ -> Nothing+  }++ruleMidnighteodendOfDay :: Rule+ruleMidnighteodendOfDay = Rule+  { name = "midnight|EOD|end of day"+  , pattern =+    [ regex "midnatt|EOD"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleDayofmonthNonOrdinalNamedmonth :: Rule+ruleDayofmonthNonOrdinalNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(omkring|cirka|runt|ca\\.)( kl\\.| klockan)?"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleUntilTimeofday :: Rule+ruleUntilTimeofday = Rule+  { name = "until <time-of-day>"+  , pattern =+    [ regex "innan|f\x00f6re|intill"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ withDirection TTime.Before td+      _ -> Nothing+  }++ruleAtTimeofday :: Rule+ruleAtTimeofday = Rule+  { name = "at <time-of-day>"+  , pattern =+    [ regex "klockan|kl.|kl|@"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "juni|jun\\.?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension Time+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "augusti|aug\\.?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleTimePartofday :: Rule+ruleTimePartofday = Rule+  { name = "<time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "((week(\\s|-)?end)|helg)(en)?"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleEomendOfMonth :: Rule+ruleEomendOfMonth = Rule+  { name = "EOM|End of month"+  , pattern =+    [ regex "EOM"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleLastYear :: Rule+ruleLastYear = Rule+  { name = "Last year"+  , pattern =+    [ regex "i fjol|ifjol"+    ]+  , prod = \_ -> tt . cycleNth TG.Year $ - 1+  }++ruleNthTimeAfterTime2 :: Rule+ruleNthTimeAfterTime2 = Rule+  { name = "nth <time> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension Time+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       Token Time td1:+       _:+       Token Time td2:+       _) -> tt $ predNthAfter (v - 1) td1 td2+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "n\x00e4sta|kommande"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleOrdinalQuarterYear :: Rule+ruleOrdinalQuarterYear = Rule+  { name = "<ordinal> quarter <year>"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m1+        m <- parseInt m2+        d <- parseInt m3+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTheOrdinalCycleAfterTime :: Rule+ruleTheOrdinalCycleAfterTime = Rule+  { name = "the <ordinal> <cycle> after <time>"+  , pattern =+    [ regex "den"+    , dimension Ordinal+    , dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "i"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "n\x00e4sta"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleADuration :: Rule+ruleADuration = Rule+  { name = "a <duration>"+  , pattern =+    [ regex "(om )?en|ett"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "morgon(en)?"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleThisPartofday :: Rule+ruleThisPartofday = Rule+  { name = "this <part-of-day>"+  , pattern =+    [ regex "i|denna"+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "denna|detta|i|nuvarande"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "(denna|detta|i|den h\x00e4r)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleDayofmonthNonOrdinalOfNamedmonth :: Rule+ruleDayofmonthNonOrdinalOfNamedmonth = Rule+  { name = "<day-of-month> (non ordinal) of <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , regex "av|i"+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "efter (lunch)"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 13, hour False 17)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleOnANamedday :: Rule+ruleOnANamedday = Rule+  { name = "on a named-day"+  , pattern =+    [ regex "p\x00e5 en"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:x:_) -> Just x+      _ -> Nothing+  }++ruleYearLatent :: Rule+ruleYearLatent = Rule+  { name = "year (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween (- 10000) 999+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ year v+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "i g\x00e5r|ig\x00e5r"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "vinter(n)"+    ]+  , prod = \_ ->+      let from = monthDay 12 21+          to = monthDay 3 20+      in tt $ interval TTime.Open (from, to)+  }++ruleAfterTimeofday :: Rule+ruleAfterTimeofday = Rule+  { name = "after <time-of-day>"+  , pattern =+    [ regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt . notLatent $ withDirection TTime.After td+      _ -> Nothing+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "juldag(en)?"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNight :: Rule+ruleNight = Rule+  { name = "night"+  , pattern =+    [ regex "natt(en)?"+    ]+  , prod = \_ ->+      let from = hour False 0+          to = hour False 4+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleDayofmonthOrdinal :: Rule+ruleDayofmonthOrdinal = Rule+  { name = "<day-of-month> (ordinal)"+  , pattern =+    [ Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->+        tt . mkLatent $ dayOfMonth v+      _ -> Nothing+  }++ruleOrdinalCycleAfterTime :: Rule+ruleOrdinalCycleAfterTime = Rule+  { name = "<ordinal> <cycle> after <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension Ordinal+    , dimension TimeGrain+    , regex "av|i|fr\x00e5n"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "maj"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "s\x00f6ndag(en)?|s\x00f6n\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do+        h <- parseInt m1+        m <- parseInt m2+        tt $ hourMinute False h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "ikv\x00e4ll"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleYear :: Rule+ruleYear = Rule+  { name = "year"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 2100+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "oktober|okt\\.?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleNamedmonthDayofmonthNonOrdinal :: Rule+ruleNamedmonthDayofmonthNonOrdinal = Rule+  { name = "<named-month> <day-of-month> (non ordinal)"+  , pattern =+    [ Predicate isAMonth+    , Predicate isDOMInteger+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleLastDayofweekOfTime :: Rule+ruleLastDayofweekOfTime = Rule+  { name = "last <day-of-week> of <time>"+  , pattern =+    [ regex "sista"+    , Predicate isADayOfWeek+    , regex "av|i"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td1:_:Token Time td2:_) ->+        tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleCycleBeforeTime :: Rule+ruleCycleBeforeTime = Rule+  { name = "<cycle> before <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "f\x00f6re"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[\\/-](0?[1-9]|1[0-2])[\\/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTimeofdayTimeofdayInterval :: Rule+ruleTimeofdayTimeofdayInterval = Rule+  { name = "<time-of-day> - <time-of-day> (interval)"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\-|till|till och med|tom"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        tt $ interval TTime.Closed (td1, td2)+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "november|nov\\.?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleDurationAfterTime :: Rule+ruleDurationAfterTime = Rule+  { name = "<duration> after <time>"+  , pattern =+    [ dimension Duration+    , regex "efter"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationAfter dd td+      _ -> Nothing+  }++ruleOrdinalQuarter :: Rule+ruleOrdinalQuarter = Rule+  { name = "<ordinal> quarter"+  , pattern =+    [ dimension Ordinal+    , Predicate $ isGrain TG.Quarter+    ]+  , prod = \tokens -> case tokens of+      (Token Ordinal (OrdinalData {TOrdinal.value = v}):_) -> tt .+        cycleNthAfter False TG.Quarter (v - 1) $ cycleNth TG.Year 0+      _ -> Nothing+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "onsdag(en)?|ons\\.?"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleTheDayofmonthOrdinal :: Rule+ruleTheDayofmonthOrdinal = Rule+  { name = "the <day-of-month> (ordinal)"+  , pattern =+    [ regex "den"+    , Predicate isDOMOrdinal+    ]+  , prod = \tokens -> case tokens of+      (_:+       Token Ordinal (OrdinalData {TOrdinal.value = v}):+       _) -> tt $ dayOfMonth v+      _ -> Nothing+  }++ruleDurationBeforeTime :: Rule+ruleDurationBeforeTime = Rule+  { name = "<duration> before <time>"+  , pattern =+    [ dimension Duration+    , regex "f\x00f6re"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_:Token Time td:_) ->+        tt $ durationBefore dd td+      _ -> Nothing+  }++rulePartofdayOfTime :: Rule+rulePartofdayOfTime = Rule+  { name = "<part-of-day> of <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "(en |ten )?den"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleEoyendOfYear :: Rule+ruleEoyendOfYear = Rule+  { name = "EOY|End of year"+  , pattern =+    [ regex "EOY"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "i morgon|imorgon"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "( )?h"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "september|sept?\\.?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleDayofmonthordinalNamedmonthYear :: Rule+ruleDayofmonthordinalNamedmonthYear = Rule+  { name = "<day-of-month>(ordinal) <named-month> year"+  , pattern =+    [ Predicate isDOMOrdinal+    , Predicate isAMonth+    , regex "(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (token:+       Token Time td:+       Token RegexMatch (GroupMatch (match:_)):+       _) -> do+         y <- parseInt match+         dom <- intersectDOM td token+         Token Time <$> intersect dom (year y)+      _ -> Nothing+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond False h m s+      _ -> Nothing+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleADuration+  , ruleAboutTimeofday+  , ruleAbsorptionOfAfterNamedDay+  , ruleAfterDuration+  , ruleAfterLunch+  , ruleAfterTimeofday+  , ruleAfterWork+  , ruleAfternoon+  , ruleAtTimeofday+  , ruleBetweenDatetimeAndDatetimeInterval+  , ruleBetweenTimeofdayAndTimeofdayInterval+  , ruleByTheEndOfTime+  , ruleChristmas+  , ruleChristmasEve+  , ruleCycleAfterTime+  , ruleCycleBeforeTime+  , ruleDatetimeDatetimeInterval+  , ruleDayofmonthNonOrdinalNamedmonth+  , ruleDayofmonthNonOrdinalOfNamedmonth+  , ruleDayofmonthOrdinal+  , ruleDayofmonthOrdinalOfNamedmonth+  , ruleDayofmonthordinalNamedmonth+  , ruleDayofmonthordinalNamedmonthYear+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleDurationAfterTime+  , ruleDurationAgo+  , ruleDurationBeforeTime+  , ruleDurationFromNow+  , ruleEomendOfMonth+  , ruleEoyendOfYear+  , ruleEvening+  , ruleExactlyTimeofday+  , ruleFromDatetimeDatetimeInterval+  , ruleFromTimeofdayTimeofdayInterval+  , ruleHhmm+  , ruleHhmmss+  , ruleHourofdayIntegerAsRelativeMinutes+  , ruleHourofdayQuarter+  , ruleHourofdayHalf+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleInduringThePartofday2+  , ruleIntersect+  , ruleIntersectBy+  , ruleIntersectByOfFromS+  , ruleLastCycle+  , ruleLastCycleOfTime+  , ruleLastDayofweekOfTime+  , ruleLastNCycle+  , ruleLastTime+  , ruleLastYear+  , ruleLunch+  , ruleMidnighteodendOfDay+  , ruleMonthDdddInterval+  , ruleMorning+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonthNonOrdinal+  , ruleNamedmonthDayofmonthOrdinal+  , ruleNewYearsDay+  , ruleNewYearsEve+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNight+  , ruleNoon+  , ruleNow+  , ruleNthTimeAfterTime+  , ruleNthTimeAfterTime2+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , ruleOnANamedday+  , ruleOnDate+  , ruleOrdinalCycleAfterTime+  , ruleOrdinalCycleOfTime+  , ruleOrdinalQuarter+  , ruleOrdinalQuarterYear+  , rulePartofdayOfTime+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleQuarterAfterpastIntegerHourofday+  , ruleHalfAfterpastIntegerHourofday+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleSeason+  , ruleSeason2+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheCycleOfTime+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleTheDayofmonthNonOrdinal+  , ruleTheDayofmonthOrdinal+  , ruleTheIdesOfNamedmonth+  , ruleTheOrdinalCycleAfterTime+  , ruleTheOrdinalCycleOfTime+  , ruleThisCycle+  , ruleThisPartofday+  , ruleThisTime+  , ruleThisnextDayofweek+  , ruleTimeAfterNext+  , ruleTimeBeforeLast+  , ruleTimePartofday+  , ruleTimeofdayApproximately+  , ruleTimeofdayLatent+  , ruleTimeofdayOclock+  , ruleTimeofdaySharp+  , ruleTimeofdayTimeofdayInterval+  , ruleToday+  , ruleTomorrow+  , ruleTonight+  , ruleUntilTimeofday+  , ruleWeekend+  , ruleWithinDuration+  , ruleYear+  , ruleYearLatent+  , ruleYearLatent2+  , ruleYesterday+  , ruleYyyymmdd+  , ruleTimezone+  ]
+ Duckling/Time/TimeZone/Parse.hs view
@@ -0,0 +1,194 @@+-- 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.Time.TimeZone.Parse+  ( parseTimezone+  ) where++import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.String+import Data.Text (Text)+import Data.Time (TimeZone(..))+import Prelude++-- `TimeZone` reads anything but only accepts timezones known+-- from the provided locale.+parseTimezone :: Text -> Maybe TimeZone+parseTimezone x = HashMap.lookup x tzs++tzs :: HashMap Text TimeZone+tzs = HashMap.fromList+  [ ( "YEKT", TimeZone 300 False "YEKT" )+  , ( "YEKST", TimeZone 360 True "YEKST" )+  , ( "YAKT", TimeZone 540 False "YAKT" )+  , ( "YAKST", TimeZone 600 True "YAKST" )+  , ( "WITA", TimeZone 480 False "WITA" )+  , ( "WIT", TimeZone 420 False "WIT" )+  , ( "WIB", TimeZone 420 False "WIB" )+  , ( "WGT", TimeZone (-180) False "WGT" )+  , ( "WGST", TimeZone (-120) True "WGST" )+  , ( "WFT", TimeZone 720 False "WFT" )+  , ( "WET", TimeZone 0 False "WET" )+  , ( "WEST", TimeZone 60 True "WEST" )+  , ( "WAT", TimeZone 60 False "WAT" )+  , ( "WAST", TimeZone 120 True "WAST" )+  , ( "VUT", TimeZone 660 False "VUT" )+  , ( "VLAT", TimeZone 660 False "VLAT" )+  , ( "VLAST", TimeZone 660 True "VLAST" )+  , ( "VET", TimeZone (-270) False "VET" )+  , ( "UZT", TimeZone 300 False "UZT" )+  , ( "UYT", TimeZone (-180) False "UYT" )+  , ( "UYST", TimeZone (-120) True "UYST" )+  , ( "UTC", TimeZone 0 False "UTC" )+  , ( "ULAT", TimeZone 480 False "ULAT" )+  , ( "TVT", TimeZone 720 False "TVT" )+  , ( "TMT", TimeZone 300 False "TMT" )+  , ( "TLT", TimeZone 540 False "TLT" )+  , ( "TKT", TimeZone 780 False "TKT" )+  , ( "TJT", TimeZone 300 False "TJT" )+  , ( "TFT", TimeZone 300 False "TFT" )+  , ( "TAHT", TimeZone (-600) False "TAHT" )+  , ( "SST", TimeZone (-660) False "SST" )+  , ( "SRT", TimeZone (-180) False "SRT" )+  , ( "SGT", TimeZone 480 False "SGT" )+  , ( "SCT", TimeZone 240 False "SCT" )+  , ( "SBT", TimeZone 660 False "SBT" )+  , ( "SAST", TimeZone 120 False "SAST" )+  , ( "SAMT", TimeZone 300 False "SAMT" )+  , ( "RET", TimeZone 240 False "RET" )+  , ( "PYT", TimeZone (-240) False "PYT" )+  , ( "PYST", TimeZone (-180) True "PYST" )+  , ( "PWT", TimeZone (-420) True "PWT" )+  , ( "PST", TimeZone (-480) False "PST" )+  , ( "PONT", TimeZone 660 False "PONT" )+  , ( "PMST", TimeZone (-180) False "PMST" )+  , ( "PMDT", TimeZone (-120) True "PMDT" )+  , ( "PKT", TimeZone 300 False "PKT" )+  , ( "PHT", TimeZone 480 False "PHT" )+  , ( "PHOT", TimeZone 780 False "PHOT" )+  , ( "PGT", TimeZone 600 False "PGT" )+  , ( "PETT", TimeZone 720 False "PETT" )+  , ( "PETST", TimeZone 720 True "PETST" )+  , ( "PET", TimeZone (-300) False "PET" )+  , ( "PDT", TimeZone (-420) False "PDT" )+  , ( "OMST", TimeZone 360 False "OMST" )+  , ( "OMSST", TimeZone 420 True "OMSST" )+  , ( "NZST", TimeZone 720 False "NZST" )+  , ( "NZDT", TimeZone 780 False "NZDT" )+  , ( "NUT", TimeZone (-660) False "NUT" )+  , ( "NST", TimeZone (-660) False "NST" )+  , ( "NPT", TimeZone (-600) True "NPT" )+  , ( "NOVT", TimeZone 360 False "NOVT" )+  , ( "NOVST", TimeZone 420 True "NOVST" )+  , ( "NFT", TimeZone 690 False "NFT" )+  , ( "NDT", TimeZone (-150) True "NDT" )+  , ( "NCT", TimeZone 660 False "NCT" )+  , ( "MYT", TimeZone 480 False "MYT" )+  , ( "MVT", TimeZone 300 False "MVT" )+  , ( "MUT", TimeZone 240 False "MUT" )+  , ( "MST", TimeZone (-420) False "MST" )+  , ( "MSK", TimeZone 180 False "MSK" )+  , ( "MSD", TimeZone 240 True "MSD" )+  , ( "MMT", TimeZone 390 False "MMT" )+  , ( "MHT", TimeZone 720 False "MHT" )+  , ( "MDT", TimeZone (-360) True "MDT" )+  , ( "MAWT", TimeZone 300 False "MAWT" )+  , ( "MART", TimeZone (-570) False "MART" )+  , ( "MAGT", TimeZone 600 False "MAGT" )+  , ( "MAGST", TimeZone 720 True "MAGST" )+  , ( "LINT", TimeZone 840 False "LINT" )+  , ( "LHST", TimeZone 630 False "LHST" )+  , ( "LHDT", TimeZone 660 True "LHDT" )+  , ( "KUYT", TimeZone 180 False "KUYT" )+  , ( "KST", TimeZone 540 False "KST" )+  , ( "KRAT", TimeZone 420 False "KRAT" )+  , ( "KRAST", TimeZone 480 True "KRAST" )+  , ( "KGT", TimeZone 360 False "KGT" )+  , ( "JST", TimeZone 540 False "JST" )+  , ( "IST", TimeZone 120 False "IST" )+  , ( "IRST", TimeZone 210 False "IRST" )+  , ( "IRKT", TimeZone 480 False "IRKT" )+  , ( "IRKST", TimeZone 540 True "IRKST" )+  , ( "IRDT", TimeZone 270 True "IRDT" )+  , ( "IOT", TimeZone 360 False "IOT" )+  , ( "IDT", TimeZone 180 True "IDT" )+  , ( "ICT", TimeZone 420 False "ICT" )+  , ( "HOVT", TimeZone 420 False "HOVT" )+  , ( "HKT", TimeZone 480 False "HKT" )+  , ( "GYT", TimeZone (-240) False "GYT" )+  , ( "GST", TimeZone 240 False "GST" )+  , ( "GMT", TimeZone 0 False "GMT" )+  , ( "GILT", TimeZone 720 False "GILT" )+  , ( "GFT", TimeZone (-180) False "GFT" )+  , ( "GET", TimeZone 240 False "GET" )+  , ( "GAMT", TimeZone (-540) False "GAMT" )+  , ( "GALT", TimeZone (-360) False "GALT" )+  , ( "FNT", TimeZone (-120) False "FNT" )+  , ( "FKT", TimeZone (-240) False "FKT" )+  , ( "FKST", TimeZone (-180) False "FKST" )+  , ( "FJT", TimeZone 720 False "FJT" )+  , ( "FJST", TimeZone 780 True "FJST" )+  , ( "EST", TimeZone (-300) False "EST" )+  , ( "EGT", TimeZone (-60) False "EGT" )+  , ( "EGST", TimeZone 0 True "EGST" )+  , ( "EET", TimeZone 120 False "EET" )+  , ( "EEST", TimeZone 180 True "EEST" )+  , ( "EDT", TimeZone (-240) True "EDT" )+  , ( "ECT", TimeZone (-300) False "ECT" )+  , ( "EAT", TimeZone 180 False "EAT" )+  , ( "EAST", TimeZone (-300) False "EAST" )+  , ( "EASST", TimeZone (-300) True "EASST" )+  , ( "DAVT", TimeZone 420 False "DAVT" )+  , ( "ChST", TimeZone 600 False "ChST" )+  , ( "CXT", TimeZone 420 False "CXT" )+  , ( "CVT", TimeZone (-60) False "CVT" )+  , ( "CST", TimeZone (-360) False "CST" )+  , ( "COT", TimeZone (-300) False "COT" )+  , ( "CLT", TimeZone (-180) False "CLT" )+  , ( "CLST", TimeZone (-180) True "CLST" )+  , ( "CKT", TimeZone (-600) False "CKT" )+  , ( "CHAST", TimeZone 765 False "CHAST" )+  , ( "CHADT", TimeZone 825 True "CHADT" )+  , ( "CET", TimeZone 60 False "CET" )+  , ( "CEST", TimeZone 120 True "CEST" )+  , ( "CDT", TimeZone 540 True "CDT" )+  , ( "CCT", TimeZone 390 False "CCT" )+  , ( "CAT", TimeZone 120 False "CAT" )+  , ( "CAST", TimeZone 180 True "CAST" )+  , ( "BTT", TimeZone 360 False "BTT" )+  , ( "BST", TimeZone (-660) False "BST" )+  , ( "BRT", TimeZone (-180) False "BRT" )+  , ( "BRST", TimeZone (-120) True "BRST" )+  , ( "BOT", TimeZone (-240) False "BOT" )+  , ( "BNT", TimeZone 480 False "BNT" )+  , ( "AZT", TimeZone 240 False "AZT" )+  , ( "AZST", TimeZone 300 True "AZST" )+  , ( "AZOT", TimeZone (-60) False "AZOT" )+  , ( "AZOST", TimeZone 0 True "AZOST" )+  , ( "AWST", TimeZone 480 False "AWST" )+  , ( "AWDT", TimeZone 540 True "AWDT" )+  , ( "AST", TimeZone (-240) False "AST" )+  , ( "ART", TimeZone (-180) False "ART" )+  , ( "AQTT", TimeZone 300 False "AQTT" )+  , ( "ANAT", TimeZone 720 False "ANAT" )+  , ( "ANAST", TimeZone 720 True "ANAST" )+  , ( "AMT", TimeZone 240 False "AMT" )+  , ( "AMST", TimeZone 300 True "AMST" )+  , ( "ALMT", TimeZone 360 False "ALMT" )+  , ( "AKST", TimeZone (-540) False "AKST" )+  , ( "AKDT", TimeZone (-480) True "AKDT" )+  , ( "AFT", TimeZone 270 False "AFT" )+  , ( "AEST", TimeZone 600 False "AEST" )+  , ( "AEDT", TimeZone 660 True "AEDT" )+  , ( "ADT", TimeZone (-180) True "ADT" )+  , ( "ACST", TimeZone 570 False "ACST" )+  , ( "ACDT", TimeZone 630 True "ACDT" )+  ]
+ Duckling/Time/Types.hs view
@@ -0,0 +1,698 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Time.Types where++import Control.Arrow ((***))+import Control.DeepSeq+import Control.Monad (join)+import Control.Applicative ((<|>))+import Data.Aeson+import Data.Hashable+import qualified Data.HashMap.Strict as H+import Data.Maybe+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Time as Time+import qualified Data.Time.Calendar.WeekDate as Time+import qualified Data.Time.LocalTime.TimeZone.Series as Series+import GHC.Generics+import TextShow (showt)+import Prelude++import Duckling.Resolve+import Duckling.TimeGrain.Types (Grain)+import qualified Duckling.TimeGrain.Types as TG++data TimeObject = TimeObject+  { start :: Time.UTCTime+  , grain :: Grain+  , end :: Maybe Time.UTCTime+  } deriving (Eq, Show)++data Form = DayOfWeek+  | TimeOfDay+    { hours :: Maybe Int+    , is12H :: Bool+    }+  | Month { month :: Int }+  | PartOfDay+  deriving (Eq, Generic, Hashable, Show, Ord, NFData)++data IntervalDirection = Before | After+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++-- Grain needed here for intersect+data TimeData = TimeData+  { timePred :: Predicate+  , latent :: Bool+  , timeGrain :: Grain+  , notImmediate :: Bool+  , form :: Maybe Form+  , direction :: Maybe IntervalDirection+  }++instance Eq TimeData where+  (==) (TimeData _ l1 g1 n1 f1 d1) (TimeData _ l2 g2 n2 f2 d2) =+    l1 == l2 && g1 == g2 && n1 == n2 && f1 == f2 && d1 == d2++instance Hashable TimeData where+  hashWithSalt s (TimeData _ latent grain imm form dir) = hashWithSalt s+    (0::Int, (latent, grain, imm, form, dir))++instance Ord TimeData where+  compare (TimeData _ l1 g1 n1 f1 d1) (TimeData _ l2 g2 n2 f2 d2) =+    case compare g1 g2 of+      EQ -> case compare f1 f2 of+        EQ -> case compare l1 l2 of+          EQ -> case compare n1 n2 of+            EQ -> compare d1 d2+            z -> z+          z -> z+        z -> z+      z -> z++instance Show TimeData where+  show (TimeData _ latent grain _ form dir) =+    "TimeData{" +++    "latent=" ++ show latent +++    ", grain=" ++ show grain +++    ", form=" ++ show form +++    ", direction=" ++ show dir +++    "}"++instance NFData TimeData where+  rnf TimeData{..} = rnf (latent, timeGrain, notImmediate, form, direction)++instance Resolve TimeData where+  type ResolvedValue TimeData = TimeValue+  resolve _ TimeData {latent = True} = Nothing+  resolve context TimeData {timePred, notImmediate, direction} = do+    t <- case ts of+      (behind, []) -> listToMaybe behind+      (_, ahead:nextAhead:_)+        | notImmediate && isJust (timeIntersect ahead refTime) -> Just nextAhead+      (_, ahead:_) -> Just ahead+    Just $ case direction of+      Nothing -> TimeValue (timeValue tzSeries t) .+        map (timeValue tzSeries) $ take 3 future+      Just d -> TimeValue (openInterval tzSeries d t) .+        map (openInterval tzSeries d) $ take 3 future+    where+      DucklingTime (Series.ZoneSeriesTime utcTime tzSeries) = referenceTime context+      refTime = TimeObject+        { start = utcTime+        , grain = TG.Second+        , end = Nothing+        }+      tc = TimeContext+        { refTime = refTime+        , tzSeries = tzSeries+        , maxTime = timePlus refTime TG.Year 2000+        , minTime = timePlus refTime TG.Year $ - 2000+        }+      ts@(_, future) = runPredicate timePred refTime tc++timedata' :: TimeData+timedata' = TimeData+  { timePred = EmptyPredicate+  , latent = False+  , timeGrain = TG.Second+  , notImmediate = False+  , form = Nothing+  , direction = Nothing+  }++data TimeContext = TimeContext+  { refTime  :: TimeObject+  , tzSeries :: Series.TimeZoneSeries+  , maxTime  :: TimeObject+  , minTime  :: TimeObject+  }++data InstantValue = InstantValue+  { vValue :: Time.ZonedTime+  , vGrain :: Grain+  }+  deriving (Show)++instance Eq InstantValue where+  (==) (InstantValue (Time.ZonedTime lt1 tz1) g1)+       (InstantValue (Time.ZonedTime lt2 tz2) g2) =+    g1 == g2 && lt1 == lt2 && tz1 == tz2++data SingleTimeValue+  = SimpleValue InstantValue+  | IntervalValue (InstantValue, InstantValue)+  | OpenIntervalValue (InstantValue, IntervalDirection)+  deriving (Show, Eq)++data TimeValue = TimeValue SingleTimeValue [SingleTimeValue]+  deriving (Show, Eq)++instance ToJSON InstantValue where+  toJSON (InstantValue value grain) = object+    [ "value" .= toRFC3339 value+    , "grain" .= grain+    ]++instance ToJSON SingleTimeValue where+  toJSON (SimpleValue value) = case toJSON value of+    Object o -> Object $ H.insert "type" (toJSON ("value" :: Text)) o+    _ -> Object H.empty+  toJSON (IntervalValue (from, to)) = object+    [ "type" .= ("interval" :: Text)+    , "from" .= toJSON from+    , "to" .= toJSON to+    ]+  toJSON (OpenIntervalValue (instant, Before)) = object+    [ "type" .= ("interval" :: Text)+    , "to" .= toJSON instant+    ]+  toJSON (OpenIntervalValue (instant, After)) = object+    [ "type" .= ("interval" :: Text)+    , "from" .= toJSON instant+    ]++instance ToJSON TimeValue where+  toJSON (TimeValue value values) = case toJSON value of+    Object o -> Object $ H.insert "values" (toJSON values) o+    _ -> Object H.empty++-- | Return a tuple of (past, future) elements+type SeriesPredicate = TimeObject -> TimeContext -> ([TimeObject], [TimeObject])++data AMPM = AM | PM+  deriving Eq++data Predicate+  = SeriesPredicate SeriesPredicate+  | EmptyPredicate+  | TimeDatePredicate -- invariant: at least one of them is Just+    { tdSecond :: Maybe Int+    , tdMinute :: Maybe Int+    , tdHour :: Maybe (Bool, Int)+    , tdAMPM :: Maybe AMPM -- only used if we have an hour+    , tdDayOfTheWeek :: Maybe Int+    , tdDayOfTheMonth :: Maybe Int+    , tdMonth :: Maybe Int+    , tdYear :: Maybe Int+    }+  | IntersectPredicate Predicate Predicate+  | TimeIntervalsPredicate TimeIntervalType Predicate Predicate++{-# ANN runPredicate ("HLint: ignore Use foldr1OrError" :: String) #-}+runPredicate :: Predicate -> SeriesPredicate+runPredicate EmptyPredicate = \_ _ -> ([], [])+runPredicate (SeriesPredicate p) = p+runPredicate TimeDatePredicate{..}+  -- This should not happen by construction, but if it does then+  -- empty time series should be ok+  | isNothing tdHour && isJust tdAMPM = \_ _ -> ([], [])+runPredicate TimeDatePredicate{..} =+  foldr1 runCompose toCompose+  where+  -- runComposePredicate performs best when the first predicate is of+  -- smaller grain, that's why we order by grain here+  toCompose = catMaybes+    [ runSecondPredicate <$> tdSecond+    , runMinutePredicate <$> tdMinute+    , uncurry (runHourPredicate tdAMPM) <$> tdHour+    , runDayOfTheWeekPredicate <$> tdDayOfTheWeek+    , runDayOfTheMonthPredicate <$> tdDayOfTheMonth+    , runMonthPredicate <$> tdMonth+    , runYearPredicate <$> tdYear+    ]+runPredicate (IntersectPredicate pred1 pred2) =+  runIntersectPredicate pred1 pred2+runPredicate (TimeIntervalsPredicate ty pred1 pred2) =+  runTimeIntervalsPredicate ty pred1 pred2++-- Don't use outside this module, use a smart constructor+emptyTimeDatePredicate :: Predicate+emptyTimeDatePredicate =+  TimeDatePredicate Nothing Nothing Nothing Nothing Nothing Nothing Nothing+    Nothing++-- Predicate smart constructors++mkSeriesPredicate :: SeriesPredicate -> Predicate+mkSeriesPredicate = SeriesPredicate++mkSecondPredicate :: Int -> Predicate+mkSecondPredicate n = emptyTimeDatePredicate { tdSecond = Just n }++mkMinutePredicate :: Int -> Predicate+mkMinutePredicate n = emptyTimeDatePredicate { tdMinute = Just n }++mkHourPredicate :: Bool -> Int -> Predicate+mkHourPredicate is12H h = emptyTimeDatePredicate { tdHour = Just (is12H, h) }++mkAMPMPredicate :: AMPM -> Predicate+mkAMPMPredicate ampm = emptyTimeDatePredicate { tdAMPM = Just ampm }++mkDayOfTheWeekPredicate :: Int -> Predicate+mkDayOfTheWeekPredicate n = emptyTimeDatePredicate { tdDayOfTheWeek = Just n }++mkDayOfTheMonthPredicate :: Int -> Predicate+mkDayOfTheMonthPredicate n = emptyTimeDatePredicate { tdDayOfTheMonth = Just n }++mkMonthPredicate :: Int -> Predicate+mkMonthPredicate n = emptyTimeDatePredicate { tdMonth = Just n }++mkYearPredicate :: Int -> Predicate+mkYearPredicate n = emptyTimeDatePredicate { tdYear = Just n }++mkIntersectPredicate :: Predicate -> Predicate -> Predicate+mkIntersectPredicate EmptyPredicate _ = EmptyPredicate+mkIntersectPredicate _ EmptyPredicate = EmptyPredicate+mkIntersectPredicate+  (TimeDatePredicate a1 b1 c1 d1 e1 f1 g1 h1)+  (TimeDatePredicate a2 b2 c2 d2 e2 f2 g2 h2)+  = fromMaybe EmptyPredicate+      (TimeDatePredicate <$>+        unify a1 a2 <*>+        unify b1 b2 <*>+        unify c1 c2 <*>+        unify d1 d2 <*>+        unify e1 e2 <*>+        unify f1 f2 <*>+        unify g1 g2 <*>+        unify h1 h2)+  where+  unify Nothing a = Just a+  unify a Nothing = Just a+  unify ma@(Just a) (Just b)+    | a == b = Just ma+    | otherwise = Nothing+mkIntersectPredicate pred1 pred2 = IntersectPredicate pred1 pred2++mkTimeIntervalsPredicate+  :: TimeIntervalType -> Predicate -> Predicate -> Predicate+mkTimeIntervalsPredicate _ EmptyPredicate _ = EmptyPredicate+mkTimeIntervalsPredicate _ _ EmptyPredicate = EmptyPredicate+-- `from (from a to b) to c` and `from c to (from a to b)` don't+-- really have a good interpretation, so abort early+mkTimeIntervalsPredicate _ TimeIntervalsPredicate{} _ = EmptyPredicate+mkTimeIntervalsPredicate _ _ TimeIntervalsPredicate{} = EmptyPredicate+mkTimeIntervalsPredicate t a b = TimeIntervalsPredicate t a b++isEmptyPredicate :: Predicate -> Bool+isEmptyPredicate EmptyPredicate = True+isEmptyPredicate _ = False++-- Predicate runners++runSecondPredicate :: Int -> SeriesPredicate+runSecondPredicate n = series+  where+  series t _ = timeSequence TG.Minute 1 anchor+    where+      Time.UTCTime _ diffTime = start t+      Time.TimeOfDay _ _ s = Time.timeToTimeOfDay diffTime+      anchor = timePlus (timeRound t TG.Second) TG.Second+        $ mod (toInteger n - floor s :: Integer) 60++runMinutePredicate :: Int -> SeriesPredicate+runMinutePredicate n = series+  where+  series t _ = timeSequence TG.Hour 1 anchor+    where+      Time.UTCTime _ diffTime = start t+      Time.TimeOfDay _ m _ = Time.timeToTimeOfDay diffTime+      rounded = timeRound t TG.Minute+      anchor = timePlus rounded TG.Minute . toInteger $ mod (n - m) 60++runHourPredicate :: Maybe AMPM -> Bool -> Int -> SeriesPredicate+runHourPredicate ampm is12H n = series+  where+  series t _ =+    ( drop 1 $+        iterate (\t -> timePlus t TG.Hour . toInteger $ - step) anchor+    , iterate (\t -> timePlus t TG.Hour $ toInteger step) anchor+    )+    where+      Time.UTCTime _ diffTime = start t+      Time.TimeOfDay h _ _ = Time.timeToTimeOfDay diffTime+      step :: Int+      step = if is12H && n <= 12 && isNothing ampm then 12 else 24+      n' = case ampm of+            Just AM -> n `mod` 12+            Just PM -> (n `mod` 12) + 12+            Nothing -> n+      rounded = timeRound t TG.Hour+      anchor = timePlus rounded TG.Hour . toInteger $ mod (n' - h) step++runAMPMPredicate :: AMPM -> SeriesPredicate+runAMPMPredicate ampm = series+  where+  series t _ = (past, future)+    where+    past = maybeShrinkFirst $+      iterate (\t -> timePlusEnd t TG.Hour . toInteger $ - step) anchor+    future = maybeShrinkFirst $+      iterate (\t -> timePlusEnd t TG.Hour $ toInteger step) anchor+    -- to produce time in the future/past we need to adjust+    -- the start/end of the first interval+    maybeShrinkFirst (a:as) =+      case timeIntersect (t { grain = TG.Day }) a of+        Nothing -> as+        Just ii -> ii:as+    maybeShrinkFirst a = a+    step :: Int+    step = 24+    n = case ampm of+          AM -> 0+          PM -> 12+    rounded = timeRound t TG.Day+    anchorStart = timePlus rounded TG.Hour n+    anchorEnd = timePlus anchorStart TG.Hour 12+    -- an interval of length 12h starting either at 12am or 12pm,+    -- the same day as input time+    anchor = timeInterval Open anchorStart anchorEnd++runDayOfTheWeekPredicate :: Int -> SeriesPredicate+runDayOfTheWeekPredicate n = series+  where+  series t _ = timeSequence TG.Day 7 anchor+    where+      Time.UTCTime day _ = start t+      (_, _, dayOfWeek) = Time.toWeekDate day+      daysUntilNextWeek = toInteger $ mod (n - dayOfWeek) 7+      anchor =+        timePlus (timeRound t TG.Day) TG.Day daysUntilNextWeek++runDayOfTheMonthPredicate :: Int -> SeriesPredicate+runDayOfTheMonthPredicate n = series+  where+  series t _ =+    ( map addDays . filter enoughDays . iterate (addMonth $ - 1) $+        addMonth (- 1) anchor+    , map addDays . filter enoughDays $ iterate (addMonth 1) anchor+    )+    where+      enoughDays :: TimeObject -> Bool+      enoughDays t = let Time.UTCTime day _ = start t+                         (year, month, _) = Time.toGregorian day+                     in n <= Time.gregorianMonthLength year month+      addDays :: TimeObject -> TimeObject+      addDays t = timePlus t TG.Day . toInteger $ n - 1+      addMonth :: Int -> TimeObject -> TimeObject+      addMonth i t = timePlus t TG.Month $ toInteger i+      roundMonth :: TimeObject -> TimeObject+      roundMonth t = timeRound t TG.Month+      rounded = roundMonth t+      Time.UTCTime day _ = start t+      (_, _, dayOfMonth) = Time.toGregorian day+      anchor = if dayOfMonth <= n then rounded else addMonth 1 rounded++runMonthPredicate :: Int -> SeriesPredicate+runMonthPredicate n = series+  where+  series t _ = timeSequence TG.Year 1 anchor+    where+      rounded =+        timePlus (timeRound t TG.Year) TG.Month . toInteger $ n - 1+      anchor = if timeStartsBeforeTheEndOf t rounded+        then rounded+        else timePlus rounded TG.Year 1++-- | Converts 2-digits to a year between 1950 and 2050+runYearPredicate :: Int -> SeriesPredicate+runYearPredicate n = series+  where+  series t _ =+    if tyear <= year+      then ([], [y])+      else ([y], [])+    where+      Time.UTCTime day _ = start t+      (tyear, _, _) = Time.toGregorian day+      year = toInteger $ if n <= 99 then mod (n + 50) 100 + 2000 - 50 else n+      y = timePlus (timeRound t TG.Year) TG.Year $ year - tyear++-- Limits how deep into lists of segments to look+safeMax :: Int+safeMax = 10++runIntersectPredicate :: Predicate -> Predicate -> SeriesPredicate+runIntersectPredicate pred1 pred2 =+  runCompose (runPredicate pred1) (runPredicate pred2)++-- Performs best when pred1 is smaller grain than pred2+runCompose :: SeriesPredicate -> SeriesPredicate -> SeriesPredicate+runCompose pred1 pred2 = series+  where+  series nowTime context = (backward, forward)+    where+    (past, future) = pred2 nowTime context+    computeSerie tokens =+      [t | time1 <- take safeMax tokens+         , t <- mapMaybe (timeIntersect time1) .+                takeWhile (startsBefore time1) .+                snd . pred1 time1 $ fixedRange time1+      ]++    startsBefore t1 this = timeStartsBeforeTheEndOf this t1+    fixedRange t1 = context {minTime = t1, maxTime = t1}++    backward = computeSerie $ takeWhile (\t ->+      timeStartsBeforeTheEndOf (minTime context) t) past+    forward = computeSerie $ takeWhile (\t ->+      timeStartsBeforeTheEndOf t (maxTime context)) future++runTimeIntervalsPredicate+  :: TimeIntervalType -> Predicate+  -> Predicate -> SeriesPredicate+runTimeIntervalsPredicate intervalType pred1 pred2 = timeSeqMap True f pred1+  where+    -- Pick the first interval *after* the given time segment+    f thisSegment ctx = case runPredicate pred2 thisSegment ctx of+      (_, firstFuture:_) -> Just $+        timeInterval intervalType thisSegment firstFuture+      _ -> Nothing++-- Limits how deep into lists of segments to look+safeMaxInterval :: Int+safeMaxInterval = 12++-- | Applies `f` to each interval yielded by `g`.+-- | Intervals including "now" are in the future.+timeSeqMap+  :: Bool+     -- Given an interval and range, compute a single new interval+  -> (TimeObject -> TimeContext -> Maybe TimeObject)+     -- First-layer series generator+  -> Predicate+     -- Series generator for values that come from `f`+  -> SeriesPredicate+timeSeqMap dontReverse f g = series+  where+  series nowTime context = (past, future)+    where+    -- computes a single interval from `f` based on each interval in the series+    applyF series = mapMaybe (\x -> f x context) $ take safeMaxInterval series++    (firstPast, firstFuture) = runPredicate g nowTime context+    (past1, future1) = (applyF firstPast, applyF firstFuture)++    -- Separate what's before and after now from the past's series+    (newFuture, stillPast) =+      span (timeStartsBeforeTheEndOf nowTime) past1+    -- A series that ends at the earliest time+    oldPast = takeWhile+      (timeStartsBeforeTheEndOf $ minTime context)+      stillPast++    -- Separate what's before and after now from the future's series+    (newPast, stillFuture) =+      break (timeStartsBeforeTheEndOf nowTime) future1+    -- A series that ends at the furthest future time+    oldFuture = takeWhile+      (\x -> timeStartsBeforeTheEndOf x $ maxTime context)+      stillFuture++    -- Reverse the list if needed?+    applyRev series = if dontReverse then series else reverse series+    (sortedPast, sortedFuture) = (applyRev newPast, applyRev newFuture)++    -- Past is the past from the future's series with the+    -- past from the past's series tacked on+    past = sortedPast ++ oldPast++    -- Future is the future from the past's series with the+    -- future from the future's series tacked on+    future = sortedFuture ++ oldFuture+++timeSequence+  :: TG.Grain+  -> Int+  -> TimeObject+  -> ([TimeObject], [TimeObject])+timeSequence grain step anchor =+  ( drop 1 $ iterate (f $ - step) anchor+  , iterate (f step) anchor+  )+  where+    f :: Int -> TimeObject -> TimeObject+    f n t = timePlus t grain $ toInteger n++-- | Zero-pad `x` to reach length `n`.+pad :: Int -> Int -> Text+pad n x+  | x <= magnitude = Text.replicate (n - Text.length s) "0" <> s+  | otherwise      = s+  where+    magnitude = round ((10 :: Float) ** fromIntegral (n - 1) :: Float)+    s = showt x++-- | Return the timezone offset portion of the RFC3339 format, e.g. "-02:00".+timezoneOffset :: Time.TimeZone -> Text+timezoneOffset (Time.TimeZone t _ _) = Text.concat [sign, hh, ":", mm]+  where+    (sign, t') = if t < 0 then ("-", negate t) else ("+", t)+    (hh, mm) = join (***) (pad 2) $ divMod t' 60++-- | Return a RFC3339 formatted time, e.g. "2013-02-12T04:30:00.000-02:00".+-- | Backward-compatible with Duckling: fraction of second is milli and padded.+toRFC3339 :: Time.ZonedTime -> Text+toRFC3339 (Time.ZonedTime (Time.LocalTime day (Time.TimeOfDay h m s)) tz) =+  Text.concat+    [ Text.pack $ Time.showGregorian day+    , "T"+    , pad 2 h+    , ":"+    , pad 2 m+    , ":"+    , pad 2 $ floor s+    , "."+    , pad 3 . round $ (s - realToFrac (floor s :: Integer)) * 1000+    , timezoneOffset tz+    ]++instantValue :: Series.TimeZoneSeries -> Time.UTCTime -> Grain -> InstantValue+instantValue tzSeries t g = InstantValue+  { vValue = fromUTC t $ Series.timeZoneFromSeries tzSeries t+  , vGrain = g+  }++timeValue :: Series.TimeZoneSeries -> TimeObject -> SingleTimeValue+timeValue tzSeries (TimeObject s g Nothing) =+  SimpleValue $ instantValue tzSeries s g+timeValue tzSeries (TimeObject s g (Just e)) = IntervalValue+  ( instantValue tzSeries s g+  , instantValue tzSeries e g+  )++openInterval+  :: Series.TimeZoneSeries -> IntervalDirection -> TimeObject -> SingleTimeValue+openInterval tzSeries direction (TimeObject s g _) = OpenIntervalValue+  ( instantValue tzSeries s g+  , direction+  )++-- -----------------------------------------------------------------+-- Time object helpers++timeRound :: TimeObject -> TG.Grain -> TimeObject+timeRound t TG.Week = TimeObject {start = s, grain = TG.Week, end = Nothing}+  where+    Time.UTCTime day diffTime = start $ timeRound t TG.Day+    (year, week, _) = Time.toWeekDate day+    newDay = Time.fromWeekDate year week 1+    s = Time.UTCTime newDay diffTime+timeRound t TG.Quarter = newTime {grain = TG.Quarter}+  where+    monthTime = timeRound t TG.Month+    Time.UTCTime day _ = start monthTime+    (_, month, _) = Time.toGregorian day+    newTime = timePlus monthTime TG.Month . toInteger $ - (mod (month - 1) 3)+timeRound t grain = TimeObject {start = s, grain = grain, end = Nothing}+  where+    Time.UTCTime day diffTime = start t+    timeOfDay = Time.timeToTimeOfDay diffTime+    (year, month, dayOfMonth) = Time.toGregorian day+    Time.TimeOfDay hours mins secs = timeOfDay+    newMonth = if grain > TG.Month then 1 else month+    newDayOfMonth = if grain > TG.Day then 1 else dayOfMonth+    newDay = Time.fromGregorian year newMonth newDayOfMonth+    newHours = if grain > TG.Hour then 0 else hours+    newMins = if grain > TG.Minute then 0 else mins+    newSecs = if grain > TG.Second then 0 else secs+    newDiffTime = Time.timeOfDayToTime $ Time.TimeOfDay newHours newMins newSecs+    s = Time.UTCTime newDay newDiffTime++timePlus :: TimeObject -> TG.Grain -> Integer -> TimeObject+timePlus (TimeObject start grain _) theGrain n = TimeObject+  { start = TG.add start theGrain n+  , grain = min grain theGrain+  , end = Nothing+  }++-- | Shifts the whole interval by n units of theGrain+-- Returned interval has the same length as the input one+timePlusEnd :: TimeObject -> TG.Grain -> Integer -> TimeObject+timePlusEnd (TimeObject start grain end) theGrain n = TimeObject+  { start = TG.add start theGrain n+  , grain = min grain theGrain+  , end = TG.add <$> end <*> return theGrain <*> return n+  }++timeEnd :: TimeObject -> Time.UTCTime+timeEnd (TimeObject start grain end) = fromMaybe (TG.add start grain 1) end++timeStartingAtTheEndOf :: TimeObject -> TimeObject+timeStartingAtTheEndOf t = TimeObject+  {start = timeEnd t, end = Nothing, grain = grain t}++-- | Closed if the interval between A and B should include B+-- Open if the interval should end right before B+data TimeIntervalType = Open | Closed+  deriving (Eq, Show)++timeInterval :: TimeIntervalType -> TimeObject -> TimeObject -> TimeObject+timeInterval intervalType t1 t2 = TimeObject+  { start = start t1+  , grain = min (grain t1) (grain t2)+  , end = Just $ case intervalType of+                   Open -> start t2+                   Closed -> timeEnd t2+  }++timeStartsBeforeTheEndOf :: TimeObject -> TimeObject -> Bool+timeStartsBeforeTheEndOf t1 t2 = start t1 < timeEnd t2++timeBefore :: TimeObject -> TimeObject -> Bool+timeBefore t1 t2 = start t1 < start t2++-- | Intersection between two `TimeObject`.+-- The resulting grain and end fields are the smallest.+-- Prefers intervals when the range is equal.+timeIntersect :: TimeObject -> TimeObject -> Maybe TimeObject+timeIntersect t1 t2+  | s1 > s2 = timeIntersect t2 t1+  | e1 <= s2 = Nothing+  | e1 < e2 || s1 == s2 && e1 == e2 && isJust end1 = Just TimeObject+    {start = s2, end = end1, grain = g'}+  | otherwise = Just t2 {grain = g'}+  where+    TimeObject s1 g1 end1 = t1+    TimeObject s2 g2 _    = t2+    e1 = timeEnd t1+    e2 = timeEnd t2+    g' = min g1 g2
+ Duckling/Time/VI/Corpus.hs view
@@ -0,0 +1,370 @@+-- 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.Time.VI.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.Time.Types hiding (Month, refTime)+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (context, allExamples)+  where+    context = testContext+      { lang = VI+      , referenceTime = refTime (2017, 2, 2, 3, 55, 0) (-2)+      }++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2017, 2, 2, 3, 55, 0) Second)+             [ "bây giờ"+             , "ngay bây giờ"+             , "ngay lúc này"+             ]+  , examples (datetime (2017, 2, 2, 0, 0, 0) Day)+             [ "hôm nay"+             , "ngày hôm nay"+             , "bữa nay"+             ]+  , examples (datetime (2017, 2, 1, 0, 0, 0) Day)+             [ "hôm qua"+             , "ngày hôm qua"+             ]+  , examples (datetime (2017, 2, 3, 0, 0, 0) Day)+             [ "ngày mai"+             ]+  , examples (datetime (2017, 1, 31, 0, 0, 0) Day)+             [ "hôm kia"+             , "ngày hôm kia"+             ]+  , examples (datetime (2017, 2, 6, 0, 0, 0) Day)+             [ "thứ 2"+             , "thứ hai"+             ]+  , examples (datetime (2017, 2, 6, 0, 0, 0) Day)+             [ "thứ 2 ngày 6 tháng 2"+             , "thứ 2 mồng 6 tháng 2"+             , "thứ hai ngày 6 tháng 2"+             ]+  , examples (datetime (2017, 2, 7, 0, 0, 0) Day)+             [ "thứ 3"+             , "thứ ba"+             ]+  , examples (datetime (2017, 2, 5, 0, 0, 0) Day)+             [ "chủ nhật"+             ]+  , examples (datetime (2017, 6, 0, 0, 0, 0) Month)+             [ "tháng 6"+             , "tháng sáu"+             ]+  , examples (datetime (2017, 3, 1, 0, 0, 0) Day)+             [ "ngày đầu tiên của tháng ba"+             , "ngày đầu tiên của tháng 3"+             ]+  , examples (datetime (2017, 3, 3, 0, 0, 0) Day)+             [ "mồng 3 tháng ba"+             , "mồng 3 tháng 3"+             ]+  , examples (datetime (2017, 3, 3, 0, 0, 0) Day)+             [ "ngày mồng 3 tháng 3 năm 2017"+             , "ngày 3 tháng 3 năm 2017"+             , "3/3/2017"+             , "3/3/17"+             , "03/03/2017"+             ]+  , examples (datetime (2017, 3, 7, 0, 0, 0) Day)+             [ "ngày mồng 7 tháng 3"+             , "ngày 7 tháng ba"+             , "7/3"+             , "07/03"+             ]+  , examples (datetime (2017, 10, 0, 0, 0, 0) Month)+             [ "tháng 10 năm 2017"+             , "tháng mười năm 2017"+             ]+  , examples (datetime (1991, 9, 3, 0, 0, 0) Day)+             [ "03/09/1991"+             , "3/9/91"+             , "3/9/1991"+             ]+  , examples (datetime (2017, 10, 12, 0, 0, 0) Day)+             [ "12 tháng 10 năm 2017"+             , "ngày 12 tháng 10 năm 2017"+             ]+  , examples (datetime (2017, 2, 9, 0, 0, 0) Day)+             [ "thứ năm tuần tới"+             , "thứ 5 tuần sau"+             ]+  , examples (datetime (2017, 3, 0, 0, 0, 0) Month)+             [ "tháng 3 tới"+             ]+  , examples (datetime (2017, 4, 9, 0, 0, 0) Day)+             [ "chủ nhật ngày mồng 9 tháng 4"+             , "chủ nhật ngày 9 tháng 4"+             ]+  , examples (datetime (2017, 2, 6, 0, 0, 0) Day)+             [ "thứ 2 ngày 6 tháng 2"+             , "thứ 2 ngày mồng 6 tháng 2"+             , "thứ hai ngày mồng 6 tháng 2"+             ]+  , examples (datetime (2018, 4, 3, 0, 0, 0) Day)+             [ "thứ 3 ngày 3 tháng 4 năm 2018"+             ]+  , examples (datetime (2017, 1, 30, 0, 0, 0) Week)+             [ "tuần này"+             ]+  , examples (datetime (2017, 1, 23, 0, 0, 0) Week)+             [ "tuần trước"+             ]+  , examples (datetime (2017, 2, 6, 0, 0, 0) Week)+             [ "tuần sau"+             ]+  , examples (datetime (2017, 1, 0, 0, 0, 0) Month)+             [ "tháng trước"+             ]+  , examples (datetime (2017, 3, 0, 0, 0, 0) Month)+             [ "tháng sau"+             ]+  , examples (datetime (2017, 1, 1, 0, 0, 0) Quarter)+             [ "quý này"+             ]+  , examples (datetime (2017, 4, 1, 0, 0, 0) Quarter)+             [ "quý sau"+             ]+  , examples (datetime (2017, 7, 1, 0, 0, 0) Quarter)+             [ "quý 3"+             , "quý ba"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "quý 4 năm 2018"+             ]+  , examples (datetime (2016, 0, 0, 0, 0, 0) Year)+             [ "năm trước"+             , "năm ngoái"+             ]+  , examples (datetime (2017, 0, 0, 0, 0, 0) Year)+             [ "năm nay"+             ]+  , examples (datetime (2018, 0, 0, 0, 0, 0) Year)+             [ "năm sau"+             ]+  , examples (datetime (2017, 1, 1, 0, 0, 0) Quarter)+             [ "quý này"+             , "quý nay"+             , "quý hiện tại"+             ]+  , examples (datetime (2017, 4, 1, 0, 0, 0) Quarter)+             [ "quý tới"+             , "quý tiếp"+             ]+  , examples (datetime (2017, 7, 1, 0, 0, 0) Quarter)+             [ "quý ba"+             , "quý 3"+             ]+  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)+             [ "quý 4 của năm 2018"+             ]+  , examples (datetime (2016, 0, 0, 0, 0, 0) Year)+             [ "năm ngoái"+             , "năm trước"+             ]+  , examples (datetime (2017, 0, 0, 0, 0, 0) Year)+             [ "năm nay"+             ]+  , examples (datetime (2018, 0, 0, 0, 0, 0) Year)+             [ "năm tiếp theo"+             , "năm kế tiếp"+             , "năm tới"+             ]+  , examples (datetime (2017, 1, 31, 0, 0, 0) Day)+             [ "thứ ba vừa rồi"+             ]+  , examples (datetime (2017, 2, 7, 0, 0, 0) Day)+             [ "thứ ba tới"+             ]+  , examples (datetime (2017, 2, 3, 0, 0, 0) Day)+             [ "thứ sáu tới"+             ]+  , examples (datetime (2017, 2, 8, 0, 0, 0) Day)+             [ "thứ tư tuần tới"+             , "thứ tư của tuần tới"+             ]+  , examples (datetime (2017, 2, 3, 0, 0, 0) Day)+             [ "thứ sáu tuần này"+             , "thứ 6 tuần này"+             , "thứ 6 của tuần này"+             ]+  , examples (datetime (2017, 2, 2, 0, 0, 0) Day)+             [ "thứ năm tuần này"+             , "thứ 5 của tuần này"+             ]+  , examples (datetime (2017, 9, 4, 0, 0, 0) Week)+             [ "tuần đầu tiên của tháng 9 năm 2017"+             ]+  , examples (datetime (2017, 2, 3, 2, 0, 0) Hour)+             [ "vào lúc 2 giờ sáng"+             , "lúc 2 giờ sáng"+             ]+  , examples (datetime (2017, 2, 3, 1, 18, 0) Minute)+             [ "1:18 sáng"+             ]+  , examples (datetime (2017, 2, 2, 15, 0, 0) Hour)+             [ "lúc 3 giờ tối"+             , "vào lúc 3 giờ chiều"+             , "vào đúng 3 giờ chiều"+             ]+  , examples (datetime (2017, 2, 2, 15, 0, 0) Hour)+             [ "vào khoảng 3 giờ chiều"+             , "khoảng 3 giờ chiều"+             ]+  , examples (datetime (2017, 2, 2, 15, 30, 0) Minute)+             [ "3 giờ rưỡi chiều"+             , "3:30 chiều"+             , "ba giờ rưỡi chiều"+             ]+  , examples (datetime (2017, 2, 2, 14, 30, 0) Minute)+             [ "2:30"+             , "hai giờ rưỡi"+             ]+  , examples (datetime (2017, 2, 2, 15, 23, 24) Second)+             [ "15:23:24"+             ]+  , examples (datetime (2017, 2, 2, 10, 45, 0) Minute)+             [ "11 giờ kém 15"+             , "10 giờ 45 phút"+             , "10:45"+             , "10 giờ 45"+             , "10h45"+             , "10g45"+             ]+  , examples (datetime (2017, 2, 2, 20, 0, 0) Hour)+             [ "8 giờ tối nay"+             ]+  , examples (datetime (2017, 4, 20, 19, 30, 0) Minute)+             [ "vào lúc 7:30 chiều ngày 20 tháng 4 năm 2017"+             , "7:30 chiều ngày 20/4/2017"+             ]+  , examples (datetimeInterval ((2017, 6, 21, 0, 0, 0), (2017, 9, 24, 0, 0, 0)) Day)+             [ "mùa hè này"+             , "mùa hè năm nay"+             ]+  , examples (datetimeInterval ((2016, 12, 21, 0, 0, 0), (2017, 3, 21, 0, 0, 0)) Day)+             [ "mùa đông này"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 18, 0, 0), (2017, 2, 3, 0, 0, 0)) Hour)+             [ "tối nay"+             , "tối hôm nay"+             ]+  , examples (datetimeInterval ((2017, 2, 3, 18, 0, 0), (2017, 2, 4, 0, 0, 0)) Hour)+             [ "tối mai"+             , "tối ngày mai"+             ]+  , examples (datetimeInterval ((2017, 2, 3, 12, 0, 0), (2017, 2, 3, 14, 0, 0)) Hour)+             [ "trưa mai"+             , "trưa ngày mai"+             ]+  , examples (datetimeInterval ((2017, 2, 1, 18, 0, 0), (2017, 2, 2, 0, 0, 0)) Hour)+             [ "tối qua"+             , "tối hôm qua"+             ]+  , examples (datetimeInterval ((2017, 2, 5, 4, 0, 0), (2017, 2, 5, 12, 0, 0)) Hour)+             [ "sáng chủ nhật"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 3, 54, 58), (2017, 2, 2, 3, 55, 0)) Second)+             [ "2 giây vừa rồi"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 3, 55, 1), (2017, 2, 2, 3, 55, 4)) Second)+             [ "3 giây tới"+             , "3 giây tiếp theo"+             , "3 s tiếp theo"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 3, 53, 0), (2017, 2, 2, 3, 55, 0)) Minute)+             [ "2 phút vừa rồi"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 3, 56, 0), (2017, 2, 2, 3, 59, 0)) Minute)+             [ "3 phút tới"+             , "3 phút tiếp theo"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 2, 0, 0), (2017, 2, 2, 3, 0, 0)) Hour)+             [ "một tiếng vừa rồi"+             , "1 giờ vừa qua"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 4, 0, 0), (2017, 2, 2, 7, 0, 0)) Hour)+             [ "3 tiếng tiếp theo"+             , "3 giờ tới"+             ]+  , examples (datetimeInterval ((2017, 1, 31, 0, 0, 0), (2017, 2, 2, 0, 0, 0)) Day)+             [ "2 ngày vừa rồi"+             , "2 ngày vừa qua"+             ]+  , examples (datetimeInterval ((2017, 2, 3, 0, 0, 0), (2017, 2, 6, 0, 0, 0)) Day)+             [ "3 ngày tới"+             , "3 ngày tiếp theo"+             ]+  , examples (datetimeInterval ((2016, 12, 0, 0, 0, 0), (2017, 2, 0, 0, 0, 0)) Month)+             [ "2 tháng vừa rồi"+             , "2 tháng qua"+             ]+  , examples (datetimeInterval ((2017, 3, 0, 0, 0, 0), (2017, 6, 0, 0, 0, 0)) Month)+             [ "3 tháng tới"+             , "ba tháng tiếp theo"+             ]+  , examples (datetimeInterval ((2015, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "2 năm vừa rồi"+             ]+  , examples (datetimeInterval ((2018, 0, 0, 0, 0, 0), (2021, 0, 0, 0, 0, 0)) Year)+             [ "3 năm tới"+             , "3 năm tiếp theo"+             ]+  , examples (datetime (2017, 2, 2, 13, 0, 0) Minute)+             [ "4pm CET"+             ]+  , examples (datetime (2017, 2, 2, 14, 0, 0) Hour)+             [ "hôm nay lúc 2 giờ chiều"+             , "lúc 2 giờ chiều"+             ]+  , examples (datetime (2017, 4, 23, 16, 0, 0) Minute)+             [ "lúc 4:00 chiều ngày 23/4"+             ]+  , examples (datetime (2017, 4, 23, 16, 0, 0) Hour)+             [ "lúc 4 giờ chiều ngày 23 tháng 4"+             ]+  , examples (datetime (2017, 2, 3, 15, 0, 0) Hour)+             [ "3 giờ chiều ngày mai"+             ]+  , examples (datetime (2017, 2, 2, 13, 30, 0) Minute)+             [ "lúc 1:30 chiều"+             , "lúc 1 giờ 30 chiều"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 13, 0, 0), (2017, 2, 2, 17, 0, 0)) Hour)+             [ "sau bữa trưa"+             ]+  , examples (datetime (2017, 2, 2, 10, 30, 0) Minute)+             [ "10:30"+             ]+  , examples (datetimeInterval ((2017, 2, 2, 4, 0, 0), (2017, 2, 2, 12, 0, 0)) Hour)+             [ "buổi sáng nay"+             ]+  , examples (datetime (2017, 2, 6, 0, 0, 0) Day)+             [ "thứ hai tới"+             , "thứ 2 tới"+             ]+  , examples (datetime (2017, 4, 0, 0, 0, 0) Month)+             [ "tháng 4"+             , "tháng tư"+             ]+  ]
+ Duckling/Time/VI/Rules.hs view
@@ -0,0 +1,1211 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.VI.Rules+  ( rules ) where++import Control.Monad (liftM2)+import Prelude+import qualified Data.Text as Text++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import Duckling.Numeral.Types (NumeralData(..))+import Duckling.Ordinal.Types (OrdinalData(..))+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import Duckling.Types+import qualified Duckling.Numeral.Types as TNumeral+import qualified Duckling.Ordinal.Types as TOrdinal+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG++ruleTtDng :: Rule+ruleTtDng = Rule+  { name = "tết dương"+  , pattern =+    [ regex "(t(\x1ebf)t d(\x01b0)(\x01a1)ng)(l(\x1ecb)ch)?"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) (2|hai)"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleDayofmonthNamedmonth :: Rule+ruleDayofmonthNamedmonth = Rule+  { name = "<day-of-month> (numeric with day symbol) <named-month>"+  , pattern =+    [ regex "(ng(\x00e0)y|m(\x1ed3)ng)( m(\x1ed3)ng)?"+    , Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleDayofweekCuiCngCaTime :: Rule+ruleDayofweekCuiCngCaTime = Rule+  { name = "<day-of-week> cuối cùng của <time>"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "cu(\x1ed1)i c(\x00f9)ng|cu(\x1ed1)i"+    , regex "c(\x1ee7)a|trong|v(\x00e0)o"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:_:Token Time td2:_) -> tt $ predLastOf td1 td2+      _ -> Nothing+  }++ruleTimeTi :: Rule+ruleTimeTi = Rule+  { name = "<time> tới"+  , pattern =+    [ Predicate isNotLatent+    , regex "t(\x1edb)i"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ predNth 0 True td+      _ -> Nothing+  }++ruleCycleCuiCngCaTime :: Rule+ruleCycleCuiCngCaTime = Rule+  { name = "<cycle> cuối cùng của <time>"+  , pattern =+    [ dimension TimeGrain+    , regex "cu(\x1ed1)i c(\x00f9)ng|cu(\x1ed1)i"+    , regex "c(\x1ee7)a|trong|v(\x00e0)o"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_:_:Token Time td:_) ->+        tt $ cycleLastOf grain td+      _ -> Nothing+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng m(\x01b0)(\x1edd)i hai"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleTimeofdayLatent2 :: Rule+ruleTimeofdayLatent2 = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ regex "(l(\x00fa)c|v(\x00e0)o)( l(\x00fa)c)?"+    , Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour False v+      _ -> Nothing+  }++ruleCchMngThng :: Rule+ruleCchMngThng = Rule+  { name = "cách mạng tháng 8"+  , pattern =+    [ regex "c(\x00e1)ch m(\x1ea1)ng th(\x00e1)ng (8|t(\x00e1)m)"+    ]+  , prod = \_ -> tt $ monthDay 8 19+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) (3|ba)"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleTimeofdayGiNg :: Rule+ruleTimeofdayGiNg = Rule+  { name = "<time-of-day> giờ đúng"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "gi(\x1edd) (\x0111)(\x00fa)ng"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) (7|b((\x1ea3)|(\x1ea9))y)"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++rulePartofdayHmNay :: Rule+rulePartofdayHmNay = Rule+  { name = "<part-of-day> (hôm )?nay"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "(h(\x00f4)m )?nay"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td+      _ -> Nothing+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng b(\x1ea3)y"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleNgyDdmmyyyy :: Rule+ruleNgyDdmmyyyy = Rule+  { name = "ngày dd/mm/yyyy"+  , pattern =+    [ regex "ng(\x00e0)y"+    , regex "(3[01]|[12]\\d|0?[1-9])[-/](0?[1-9]|1[0-2])[/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do+        y <- parseInt m3+        m <- parseInt m2+        d <- parseInt m1+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) (5|n(\x0103)m)"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++rulePartofdayTime :: Rule+rulePartofdayTime = Rule+  { name = "<part-of-day> <time>"+  , pattern =+    [ Predicate isAPartOfDay+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleQuarterNumber :: Rule+ruleQuarterNumber = Rule+  { name = "quarter <number>"+  , pattern =+    [ Predicate $ isGrain TG.Quarter+    , dimension Numeral+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt . cycleNthAfter True TG.Quarter (n - 1) $+          cycleNth TG.Year 0+      _ -> Nothing+  }++ruleSeason4 :: Rule+ruleSeason4 = Rule+  { name = "season"+  , pattern =+    [ regex "m(\x00f9)a? xu(\x00e2)n"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 3 20, monthDay 6 21)+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "(bu(\x1ed5)i )?(t(\x1ed1)i|(\x0111)(\x00ea)m)"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleQucTLaoNg :: Rule+ruleQucTLaoNg = Rule+  { name = "quốc tế lao động"+  , pattern =+    [ regex "(ng(\x00e0)y )?qu(\x1ed1)c t(\x1ebf) lao (\x0111)(\x00f4)ng"+    ]+  , prod = \_ -> tt $ monthDay 5 1+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "(t(\x1edb)i|k(\x1ebf)|sau|ti(\x1ebf)p)( theo)?( ti(\x1ebf)p)?"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng (gi(\x00ea)ng|m(\x1ed9)t)"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleTimeofdayApproximately :: Rule+ruleTimeofdayApproximately = Rule+  { name = "<time-of-day> approximately"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "g(\x1ea7)n"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleQuarterNumberOfYear :: Rule+ruleQuarterNumberOfYear = Rule+  { name = "quarter <number> of <year>"+  , pattern =+    [ Predicate $ isGrain TG.Quarter+    , dimension Numeral+    , regex "c(\x1ee7)a|trong"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:_:Token Time td:_) -> do+        n <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (n - 1) td+      _ -> Nothing+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng ba"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleLunch :: Rule+ruleLunch = Rule+  { name = "lunch"+  , pattern =+    [ regex "(bu(\x1ed5)i )?tr(\x01b0)a"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 14)+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "tr(\x01b0)(\x1edb)c|qua|v(\x1eeb)a r(\x1ed3)i|ngo(\x00e1)i"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleDdmm :: Rule+ruleDdmm = Rule+  { name = "dd/mm"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])/(0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        d <- parseInt dd+        m <- parseInt mm+        tt $ monthDay m d+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "(bu(\x1ed5)i )?chi(\x1ec1)u"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 12, hour False 19)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng t(\x01b0)|th(\x00e1)ng b(\x1ed1)n"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleHmNay :: Rule+ruleHmNay = Rule+  { name = "hôm nay"+  , pattern =+    [ regex "((ngay )?h(\x00f4)m|b(\x1eef)a) nay"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleAtHhmm :: Rule+ruleAtHhmm = Rule+  { name = "at hh:mm"+  , pattern =+    [ regex "(l(\x00fa)c|v(\x00e0)o)( l(\x00fa)c)?"+    , regex "((?:[01]?\\d)|(?:2[0-3]))[:.hg]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleHourofdayInteger :: Rule+ruleHourofdayInteger = Rule+  { name = "<hour-of-day> <integer>"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleHourofdayQuarter :: Rule+ruleHourofdayQuarter = Rule+  { name = "(hour-of-day) quarter"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "k(\x00e9)m"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        Token Time <$> minutesBefore n td+      _ -> Nothing+  }++ruleHourofdayHalf :: Rule+ruleHourofdayHalf = Rule+  { name = "(hour-of-day) half"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "r(\x01b0)(\x1ee1)i"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->+        tt $ hourMinute is12H hours 30+      _ -> Nothing+  }++ruleHourofdayIntegerPht :: Rule+ruleHourofdayIntegerPht = Rule+  { name = "<hour-of-day> <integer> phút"+  , pattern =+    [ Predicate isAnHourOfDay+    , Predicate $ isIntegerBetween 1 59+    , regex "ph(\x00fa)t"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute is12H hours n+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) 6|th(\x1ee9) s(\x00e1)u"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleCuiNm :: Rule+ruleCuiNm = Rule+  { name = "cuối năm"+  , pattern =+    [ regex "cu(\x1ed1)i n(\x0103)m"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleQuarterNumberYear :: Rule+ruleQuarterNumberYear = Rule+  { name = "quarter <number> <year>"+  , pattern =+    [ Predicate $ isGrain TG.Quarter+    , dimension Numeral+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token Time td:_) -> do+        v <- getIntValue token+        tt $ cycleNthAfter False TG.Quarter (v - 1) td+      _ -> Nothing+  }++ruleTimeofdayLatent :: Rule+ruleTimeofdayLatent = Rule+  { name = "time-of-day (latent)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        n <- getIntValue token+        tt . mkLatent $ hour True n+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng hai"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleExactlyTimeofday :: Rule+ruleExactlyTimeofday = Rule+  { name = "exactly <time-of-day>"+  , pattern =+    [ regex "(v(\x00e0)o )?(\x0111)(\x00fa)ng"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleNgyHmQua :: Rule+ruleNgyHmQua = Rule+  { name = "ngày hôm qua"+  , pattern =+    [ regex "(ng(\x00e0)y )?(h(\x00f4)m )?qua"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleSeason3 :: Rule+ruleSeason3 = Rule+  { name = "season"+  , pattern =+    [ regex "m(\x00f9)a? (\x0111)(\x00f4)ng"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 12 21, monthDay 3 20)+  }++ruleSeason :: Rule+ruleSeason = Rule+  { name = "season"+  , pattern =+    [ regex "m(\x00f9)a? (h(\x00e8)|h(\x1ea1))"+    ]+  , prod = \_ -> tt $ interval TTime.Open (monthDay 6 21, monthDay 9 23)+  }++ruleDayofmonthNamedmonth2 :: Rule+ruleDayofmonthNamedmonth2 = Rule+  { name = "<day-of-month> <named-month>"+  , pattern =+    [ Predicate isDOMInteger+    , Predicate isAMonth+    ]+  , prod = \tokens -> case tokens of+      (token:Token Time td:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleYearNumericWithYearSymbol :: Rule+ruleYearNumericWithYearSymbol = Rule+  { name = "year (numeric with year symbol)"+  , pattern =+    [ regex "n(\x0103)m"+    , Predicate $ isIntegerBetween 1000 9999+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        n <- getIntValue token+        tt $ year n+      _ -> Nothing+  }++ruleAfterWork :: Rule+ruleAfterWork = Rule+  { name = "after work"+  , pattern =+    [ regex "(sau gi(\x1edd) l(\x00e0)m|sau gi(\x1edd) tan t(\x1ea7)m|l(\x00fa)c tan t(\x1ea7)m)"+    ]+  , prod = \_ -> Token Time . partOfDay . notLatent <$>+      intersect (cycleNth TG.Day 0)+      (interval TTime.Open (hour False 17, hour False 21))+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    , regex "tr(\x01b0)(\x1edb)c|qua|v(\x1eeb)a r(\x1ed3)i|ngo(\x00e1)i|v(\x1eeb)a qua"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        n <- getIntValue token+        tt . cycleN True grain $ - n+      _ -> Nothing+  }++ruleTimeofdaySharp :: Rule+ruleTimeofdaySharp = Rule+  { name = "<time-of-day> sharp"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(\x0111)(\x00fa)ng"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleAboutTimeofday :: Rule+ruleAboutTimeofday = Rule+  { name = "about <time-of-day>"+  , pattern =+    [ regex "(v(\x00e0)o )?kho(\x1ea3)ng"+    , Predicate isATimeOfDay+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleLTnhNhn :: Rule+ruleLTnhNhn = Rule+  { name = "lễ tình nhân"+  , pattern =+    [ regex "(ng(\x00e0)y )?(l(\x1ec5))? t(\x00ec)nh nh(\x00e2)n"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng s(\x00e1)u"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng t(\x00e1)m"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleCuiThng :: Rule+ruleCuiThng = Rule+  { name = "cuối tháng"+  , pattern =+    [ regex "cu(\x1ed1)i th(\x00e1)ng"+    ]+  , prod = \_ -> tt $ cycleNth TG.Month 1+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "(cu(\x1ed1)i|h(\x1ebf)t) tu(\x1ea7)n"+    ]+  , prod = \_ -> do+      fri <- intersect (dayOfWeek 5) (hour False 18)+      mon <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (fri, mon)+  }++ruleTimeofdaySngchiuti :: Rule+ruleTimeofdaySngchiuti = Rule+  { name = "<time-of-day> sáng|chiều|tối"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(s(\x00e1)ng|chi(\x1ec1)u|t(\x1ed1)i)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "s\225ng"+      _ -> Nothing+  }++ruleTimeTrc :: Rule+ruleTimeTrc = Rule+  { name = "<time> trước"+  , pattern =+    [ dimension Time+    , regex "tr(\x01b0)(\x1edb)c|v(\x1eeb)a r(\x1ed3)i"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleTimeofdayGi :: Rule+ruleTimeofdayGi = Rule+  { name = "time-of-day giờ"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "gi(\x1edd)"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ notLatent td+      _ -> Nothing+  }++ruleQucKhnh :: Rule+ruleQucKhnh = Rule+  { name = "quốc khánh"+  , pattern =+    [ regex "qu(\x1ed1)c kh(\x00e1)nh"+    ]+  , prod = \_ -> tt $ monthDay 9 3+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleIntersectByOfFromS :: Rule+ruleIntersectByOfFromS = Rule+  { name = "intersect by \"of\", \"from\", \"'s\""+  , pattern =+    [ Predicate isNotLatent+    , regex "c(\x1ee7)a|trong"+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    , regex "(t(\x1edb)i|k(\x1ebf)|sau|ti(\x1ebf)p)( theo)?( ti(\x1ebf)p)?"+    ]+  , prod = \tokens -> case tokens of+      (token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "(bu(\x1ed5)i )?s(\x00e1)ng"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 4, hour False 12)+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ dimension TimeGrain+    , regex "nay|n(\x00e0)y|hi(\x1ec7)n t(\x1ea1)i|h(\x00f4)m nay|n(\x0103)m nay"+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleNoon2 :: Rule+ruleNoon2 = Rule+  { name = "noon"+  , pattern =+    [ regex "(bu(\x1ed5)i )?(t(\x1ed1)i|(\x0111)(\x00ea)m)"+    ]+  , prod = \_ -> tt . partOfDay . mkLatent $+      interval TTime.Open (hour False 18, hour False 0)+  }++ruleAfterLunch :: Rule+ruleAfterLunch = Rule+  { name = "after lunch"+  , pattern =+    [ regex "(sau|qua) (bu(\x1ed5)i |b(\x1eef)a )?tr(\x01b0)a"+    ]+  , prod = \_ -> Token Time . partOfDay . notLatent <$>+      intersect (cycleNth TG.Day 0)+      (interval TTime.Open (hour False 13, hour False 17))+  }++ruleSeason2 :: Rule+ruleSeason2 = Rule+  { name = "season"+  , pattern =+    [ regex "m(\x00f9)a? thu"+    ]+  , prod = \_ ->+      tt $ interval TTime.Open (monthDay 9 23, monthDay 12 21)+  }++ruleTimeNy :: Rule+ruleTimeNy = Rule+  { name = "<time> này"+  , pattern =+    [ dimension Time+    , regex "n(\x00e0)y|nay"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> tt $ predNth 0 False td+      _ -> Nothing+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "(in the )?([ap])(\\s|\\.)?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (_:ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleNgyMai :: Rule+ruleNgyMai = Rule+  { name = "ngày mai"+  , pattern =+    [ regex "(ng(\x00e0)y )?mai"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleOrdinalCycleOfTime :: Rule+ruleOrdinalCycleOfTime = Rule+  { name = "<ordinal> <cycle> of <time>"+  , pattern =+    [ dimension TimeGrain+    , dimension Ordinal+    , regex "c(\x1ee7)a|trong"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token TimeGrain grain:Token Ordinal od:_:Token Time td:_) ->+        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng n(\x0103)m"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "ch(\x1ee7) nh(\x1ead)t"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++ruleMonthNumericWithMonthSymbol :: Rule+ruleMonthNumericWithMonthSymbol = Rule+  { name = "month (numeric with month symbol)"+  , pattern =+    [ regex "th(\x00e1)ng"+    , Predicate $ isIntegerBetween 1 12+    ]+  , prod = \tokens -> case tokens of+      (_:token:_) -> do+        v <- getIntValue token+        tt $ month v+      _ -> Nothing+  }++ruleHhmm :: Rule+ruleHhmm = Rule+  { name = "hh:mm"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.hg]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "(t(\x1ed1)i|(\x0111)(\x00ea)m)( h(\x00f4)m)? nay"+    ]+  , prod = \_ ->+      let today = cycleNth TG.Day 0+          evening = interval TTime.Open (hour False 18, hour False 0) in+        Token Time . partOfDay . notLatent <$> intersect today evening+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) (isGrainFinerThan TG.Day) isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng m(\x01b0)(\x1edd)i"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleByGi :: Rule+ruleByGi = Rule+  { name = "bây giờ"+  , pattern =+    [ regex "(ngay )?(b(\x00e2)y gi(\x1edd)|l(\x00fa)c n(\x00e0)y)"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleNgyDdmm :: Rule+ruleNgyDdmm = Rule+  { name = "ngày dd/mm"+  , pattern =+    [ regex "ng(\x00e0)y"+    , regex "(3[01]|[12]\\d|0?[1-9])/(0?[1-9]|1[0-2])"+    ]+  , prod = \tokens -> case tokens of+      (_:Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do+        d <- parseInt dd+        m <- parseInt mm+        tt $ monthDay m d+      _ -> Nothing+  }++ruleHhmmMilitaryAmpm :: Rule+ruleHhmmMilitaryAmpm = Rule+  { name = "hhmm (military) am|pm"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "([ap])\\.?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):+       Token RegexMatch (GroupMatch (ap:_)):+       _) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "a"+      _ -> Nothing+  }++ruleHhmmMilitarySngchiuti :: Rule+ruleHhmmMilitarySngchiuti = Rule+  { name = "hhmm (military) sáng|chiều|tối"+  , pattern =+    [ regex "((?:1[012]|0?\\d))([0-5]\\d)"+    , regex "(s(\x00e1)ng|chi(\x1ec1)u|t(\x1ed1)i)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):+       Token RegexMatch (GroupMatch (ap:_)):+       _) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . timeOfDayAMPM (hourMinute True h m) $+          Text.toLower ap == "s\225ng"+      _ -> Nothing+  }++ruleDdmmyyyy :: Rule+ruleDdmmyyyy = Rule+  { name = "dd/mm/yyyy"+  , pattern =+    [ regex "(3[01]|[12]\\d|0?[1-9])[-/](0?[1-9]|1[0-2])[/-](\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng m(\x01b0)(\x1edd)i m(\x1ed9)t"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleGingSinh :: Rule+ruleGingSinh = Rule+  { name = "giáng sinh"+  , pattern =+    [ regex "(ng(\x00e0)y )(xmas|christmas|gi(\x00e1)ng sinh)?"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "th(\x1ee9) 4|th(\x1ee9) b(\x1ed1)n|th(\x1ee9) t(\x01b0)"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleNgyHmKia :: Rule+ruleNgyHmKia = Rule+  { name = "ngày hôm kia"+  , pattern =+    [ regex "(ng(\x00e0)y )?h(\x00f4)m kia"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleDayofweekTi :: Rule+ruleDayofweekTi = Rule+  { name = "<day-of-week> tới"+  , pattern =+    [ Predicate isADayOfWeek+    , regex "t(\x1edb)i"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "th(\x00e1)ng ch(\x00ed)n"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleHhmmss :: Rule+ruleHhmmss = Rule+  { name = "hh:mm:ss"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        s <- parseInt ss+        tt $ hourMinuteSecond True h m s+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAboutTimeofday+  , ruleAfterLunch+  , ruleAfterWork+  , ruleAfternoon+  , ruleAtHhmm+  , ruleByGi+  , ruleCchMngThng+  , ruleCuiNm+  , ruleCuiThng+  , ruleCycleCuiCngCaTime+  , ruleDayofmonthNamedmonth+  , ruleDayofmonthNamedmonth2+  , ruleDayofweekCuiCngCaTime+  , ruleDayofweekTi+  , ruleDdmm+  , ruleDdmmyyyy+  , ruleExactlyTimeofday+  , ruleGingSinh+  , ruleHhmm+  , ruleHhmmMilitaryAmpm+  , ruleHhmmMilitarySngchiuti+  , ruleHhmmss+  , ruleHmNay+  , ruleHourofdayHalf+  , ruleHourofdayInteger+  , ruleHourofdayIntegerPht+  , ruleHourofdayQuarter+  , ruleIntersect+  , ruleIntersectByOfFromS+  , ruleLTnhNhn+  , ruleLastCycle+  , ruleLastNCycle+  , ruleLunch+  , ruleMonthNumericWithMonthSymbol+  , ruleMorning+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNgyDdmm+  , ruleNgyDdmmyyyy+  , ruleNgyHmKia+  , ruleNgyHmQua+  , ruleNgyMai+  , ruleNoon+  , ruleNoon2+  , ruleOrdinalCycleOfTime+  , rulePartofdayHmNay+  , rulePartofdayTime+  , ruleQuarterNumber+  , ruleQuarterNumberOfYear+  , ruleQuarterNumberYear+  , ruleQucKhnh+  , ruleQucTLaoNg+  , ruleSeason+  , ruleSeason2+  , ruleSeason3+  , ruleSeason4+  , ruleThisCycle+  , ruleTimeNy+  , ruleTimeTi+  , ruleTimeTrc+  , ruleTimeofdayAmpm+  , ruleTimeofdayApproximately+  , ruleTimeofdayGi+  , ruleTimeofdayGiNg+  , ruleTimeofdayLatent+  , ruleTimeofdayLatent2+  , ruleTimeofdaySharp+  , ruleTimeofdaySngchiuti+  , ruleTimezone+  , ruleTonight+  , ruleTtDng+  , ruleWeekend+  , ruleYearNumericWithYearSymbol+  , ruleYyyymmdd+  ]
+ Duckling/Time/ZH/Corpus.hs view
@@ -0,0 +1,418 @@+-- 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.Time.ZH.Corpus+  ( corpus ) where++import Prelude+import Data.String++import Duckling.Lang+import Duckling.Resolve+import Duckling.Time.Corpus+import Duckling.TimeGrain.Types hiding (add)+import Duckling.Testing.Types hiding (examples)++corpus :: Corpus+corpus = (testContext {lang = ZH}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)+             [ "现在"+             , "此时"+             , "此刻"+             , "当前"+             , "現在"+             , "此時"+             , "當前"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "今天"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)+             [ "昨天"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "明天"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "后天"+             , "後天"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "前天"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "星期一"+             , "礼拜一"+             , "周一"+             , "禮拜一"+             , "週一"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "星期二"+             , "礼拜二"+             , "周二"+             , "禮拜二"+             , "週二"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "星期三"+             , "礼拜三"+             , "周三"+             , "禮拜三"+             , "週三"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "星期四"+             , "礼拜四"+             , "周四"+             , "禮拜四"+             , "週四"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "星期五"+             , "礼拜五"+             , "周五"+             , "禮拜五"+             , "週五"+             ]+  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)+             [ "星期六"+             , "礼拜六"+             , "周六"+             , "禮拜六"+             , "週六"+             ]+  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)+             [ "星期日"+             , "星期天"+             , "礼拜天"+             , "周日"+             , "禮拜天"+             , "週日"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)+             [ "这周末"+             , "這週末"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)+             [ "周一早上"+             , "周一早晨"+             , "礼拜一早上"+             , "礼拜一早晨"+             , "週一早上"+             , "週一早晨"+             , "禮拜一早上"+             , "禮拜一早晨"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "上周日"+             , "上星期天"+             , "上礼拜天"+             , "上週日"+             , "上星期天"+             , "上禮拜天"+             ]+  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)+             [ "周日, 二月十号"+             , "星期天, 二月十号"+             , "礼拜天, 二月十号"+             , "週日, 二月十號"+             , "星期天, 二月十號"+             , "禮拜天, 二月十號"+             ]+  , examples (datetime (2013, 10, 7, 0, 0, 0) Day)+             [ "十月第一个星期一"+             , "十月的第一个星期一"+             ]+  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)+             [ "上周二"+             , "上礼拜二"+             , "上週二"+             , "上禮拜二"+             ]+  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)+             [ "三月一号"+             , "三月一日"+             , "三月一號"+             ]+  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)+             [ "2015年3月3号"+             , "2015年3月三号"+             , "2015年三月3号"+             , "2015年三月三号"+             , "2015年3月3號"+             , "2015年3月三號"+             , "2015年三月3號"+             , "2015年三月三號"+             , "3/3/2015"+             , "3/3/15"+             , "2015-3-3"+             , "2015-03-03"+             ]+  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)+             [ "2013年2月15号"+             , "2013年二月十五号"+             , "2月15号"+             , "二月十五号"+             , "2013年2月15號"+             , "2013年二月十五號"+             , "2月15號"+             , "二月十五號"+             , "2/15"+             ]+  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)+             [ "10/31/1974"+             , "10/31/74"+             ]+  , examples (datetimeInterval ((2013, 2, 15, 4, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)+             [ "二月十五号早上"+             , "二月十五号早晨"+             , "2月15号早上"+             , "2月15号早晨"+             , "二月十五號早上"+             , "二月十五號早晨"+             , "2月15號早上"+             , "2月15號早晨"+             ]+  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)+             [ "下周二"+             , "下週二"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "这周三"+             , "这礼拜三"+             , "這週三"+             , "這禮拜三"+             ]+  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)+             [ "下周三"+             , "下礼拜三"+             , "下週三"+             , "下禮拜三"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)+             [ "这周一"+             , "这礼拜一"+             , "這週一"+             , "這禮拜一"+             ]+  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)+             [ "这周二"+             , "这礼拜二"+             , "這週二"+             , "這禮拜二"+             ]+  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)+             [ "这周"+             , "这一周"+             , "这礼拜"+             , "这一礼拜"+             , "這週"+             , "這一周"+             , "這禮拜"+             , "這一禮拜"+             ]+  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)+             [ "上周"+             , "上週"+             ]+  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)+             [ "下周"+             , "下週"+             ]+  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)+             [ "上月"+             , "上个月"+             , "上個月"+             ]+  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)+             [ "下月"+             , "下个月"+             , "下個月"+             ]+  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)+             [ "去年"+             ]+  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)+             [ "今年"+             , "这一年"+             , "這一年"+             ]+  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)+             [ "明年"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)+             [ "上两秒"+             , "上二秒"+             , "前两秒"+             , "前二秒"+             , "上兩秒"+             , "前兩秒"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)+             [ "下三秒"+             , "后三秒"+             , "後三秒"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)+             [ "上两分钟"+             , "上二分钟"+             , "前两分钟"+             , "前二分钟"+             , "上兩分鐘"+             , "上二分鐘"+             , "前兩分鐘"+             , "前二分鐘"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)+             [ "下三分钟"+             , "后三分钟"+             , "下三分鐘"+             , "後三分鐘"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 2, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)+             [ "上两小时"+             , "上二小时"+             , "前两小时"+             , "前二小时"+             , "上兩小時"+             , "上二小時"+             , "前兩小時"+             , "前二小時"+             ]+  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)+             [ "下三小时"+             , "后三小时"+             , "下三小時"+             , "後三小時"+             ]+  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)+             [ "上两天"+             , "前两天"+             , "上兩天"+             , "前兩天"+             ]+  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)+             [ "下三天"+             , "后三天"+             , "後三天"+             ]+  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)+             [ "上两周"+             , "上二周"+             , "上兩週"+             , "上二週"+             ]+  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)+             [ "下三周"+             , "下三个周"+             , "下三週"+             , "下三個週"+             ]+  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)+             [ "上两个月"+             , "上二个月"+             , "上二月"+             , "前两个月"+             , "前二个月"+             , "前两月"+             , "上兩個月"+             , "上二個月"+             , "前兩個月"+             , "前二個月"+             , "前兩月"+             ]+  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)+             [ "下三个月"+             , "后三个月"+             , "後三個月"+             ]+  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)+             [ "前两年"+             , "前兩年"+             ]+  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)+             [ "下三年"+             ]+  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)+             [ "三点"+             , "三點"+             , "3pm"+             ]+  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)+             [ "下午三点十五"+             , "下午3:15"+             , "15:15"+             , "3:15pm"+             , "3:15PM"+             , "3:15p"+             , "下午三點十五"+             ]+  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)+             [ "4pm CET"+             ]+  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)+             [ "2015年4月14号"+             ]+  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)+             [ "今晚8点"+             , "今晚八点"+             , "今晚8點"+             , "今晚八點"+             ]+  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)+             [ "元旦"+             , "元旦节"+             , "元旦節"+             ]+  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)+             [ "情人节"+             , "情人節"+             ]+  , examples (datetime (2013, 3, 8, 0, 0, 0) Day)+             [ "妇女节"+             , "婦女節"+             ]+  , examples (datetime (2013, 5, 1, 0, 0, 0) Day)+             [ "劳动节"+             , "勞動節"+             ]+  , examples (datetime (2013, 6, 1, 0, 0, 0) Day)+             [ "儿童节"+             , "兒童節"+             ]+  , examples (datetime (2013, 8, 1, 0, 0, 0) Day)+             [ "建军节"+             , "建軍節"+             ]+  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)+             [ "国庆"+             , "國慶"+             , "国庆节"+             , "國慶節"+             ]+  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)+             [ "圣诞"+             , "聖誕"+             , "圣诞节"+             , "聖誕節"+             ]+  , examples (datetimeInterval ((2013, 10, 1, 18, 0, 0), (2013, 10, 2, 0, 0, 0)) Hour)+             [ "国庆节晚上"+             , "國慶節晚上"+             ]+  , examples (datetime (2013, 6, 1, 15, 15, 0) Minute)+             [ "儿童节下午三点十五"+             , "兒童節下午三點十五"+             ]+  ]
+ Duckling/Time/ZH/Rules.hs view
@@ -0,0 +1,1213 @@+-- 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 NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Time.ZH.Rules+  ( rules ) where++import Control.Monad (liftM2)+import qualified Data.Text as Text+import Prelude++import Duckling.Dimensions.Types+import Duckling.Numeral.Helpers (parseInt)+import qualified Duckling.Ordinal.Types as TOrdinal+import Duckling.Regex.Types+import Duckling.Time.Helpers+import Duckling.Time.Types (TimeData (..))+import qualified Duckling.Time.Types as TTime+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++ruleNamedday :: Rule+ruleNamedday = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x4e00|\x5468\x4e00|\x793c\x62dc\x4e00|\x79ae\x62dc\x4e00|\x9031\x4e00"+    ]+  , prod = \_ -> tt $ dayOfWeek 1+  }++ruleTheDayAfterTomorrow :: Rule+ruleTheDayAfterTomorrow = Rule+  { name = "the day after tomorrow"+  , pattern =+    [ regex "\x540e\x5929|\x5f8c\x5929"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 2+  }++ruleNamedmonth12 :: Rule+ruleNamedmonth12 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x5341\x4e8c\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 12+  }++ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule+ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule+  { name = "relative minutes to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(\x70b9|\x9ede)\x5dee"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleRelativeMinutesTotillbeforeNoonmidnight :: Rule+ruleRelativeMinutesTotillbeforeNoonmidnight = Rule+  { name = "relative minutes to|till|before noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x5dee"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_:token:_) -> do+        n <- getIntValue token+        t <- minutesBefore n td+        Just $ Token Time t+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastIntegerHourofday :: Rule+ruleRelativeMinutesAfterpastIntegerHourofday = Rule+  { name = "relative minutes after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x70b9|\x9ede"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleRelativeMinutesAfterpastNoonmidnight :: Rule+ruleRelativeMinutesAfterpastNoonmidnight = Rule+  { name = "relative minutes after|past noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x8fc7"+    , Predicate $ isIntegerBetween 1 59+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _:+       token:+       _) -> do+        n <- getIntValue token+        tt $ hourMinute True hours n+      _ -> Nothing+  }++ruleQuarterTotillbeforeIntegerHourofday :: Rule+ruleQuarterTotillbeforeIntegerHourofday = Rule+  { name = "quarter to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(\x70b9|\x9ede)\x5dee"+    , regex "\x4e00\x523b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }+ruleQuarterTotillbeforeNoonmidnight :: Rule+ruleQuarterTotillbeforeNoonmidnight = Rule+  { name = "quarter to|till|before noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x5dee"+    , regex "\x4e00\x523b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 15 td+      _ -> Nothing+  }+ruleQuarterAfterpastIntegerHourofday :: Rule+ruleQuarterAfterpastIntegerHourofday = Rule+  { name = "quarter after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x70b9|\x9ede"+    , regex "\x4e00\x523b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }+ruleQuarterAfterpastNoonmidnight :: Rule+ruleQuarterAfterpastNoonmidnight = Rule+  { name = "quarter after|past noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x8fc7"+    , regex "\x4e00\x523b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 15+      _ -> Nothing+  }++ruleHalfTotillbeforeIntegerHourofday :: Rule+ruleHalfTotillbeforeIntegerHourofday = Rule+  { name = "half to|till|before <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "(\x70b9|\x9ede)\x5dee"+    , regex "\x534a"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }+ruleHalfTotillbeforeNoonmidnight :: Rule+ruleHalfTotillbeforeNoonmidnight = Rule+  { name = "half to|till|before noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x5dee"+    , regex "\x534a"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) -> Token Time <$> minutesBefore 30 td+      _ -> Nothing+  }+ruleHalfAfterpastIntegerHourofday :: Rule+ruleHalfAfterpastIntegerHourofday = Rule+  { name = "half after|past <integer> (hour-of-day)"+  , pattern =+    [ Predicate isAnHourOfDay+    , regex "\x70b9|\x9ede"+    , regex "\x534a"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }+ruleHalfAfterpastNoonmidnight :: Rule+ruleHalfAfterpastNoonmidnight = Rule+  { name = "half after|past noon|midnight"+  , pattern =+    [ Predicate isMidnightOrNoon+    , regex "\x8fc7"+    , regex "\x534a"+    ]+  , prod = \tokens -> case tokens of+      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:+       _) -> tt $ hourMinute True hours 30+      _ -> Nothing+  }++ruleNamedday2 :: Rule+ruleNamedday2 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x4e8c|\x5468\x4e8c|\x793c\x62dc\x4e8c|\x79ae\x62dc\x4e8c|\x9031\x4e8c"+    ]+  , prod = \_ -> tt $ dayOfWeek 2+  }++ruleValentinesDay :: Rule+ruleValentinesDay = Rule+  { name = "valentine's day"+  , pattern =+    [ regex "\x60c5\x4eba(\x8282|\x7bc0)"+    ]+  , prod = \_ -> tt $ monthDay 2 14+  }++ruleHhmmTimeofday :: Rule+ruleHhmmTimeofday = Rule+  { name = "hh:mm (time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3])):([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt $ hourMinute True h m+      _ -> Nothing+  }++ruleThisDayofweek :: Rule+ruleThisDayofweek = Rule+  { name = "this <day-of-week>"+  , pattern =+    [ regex "\x8fd9|\x9019"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleNthTimeOfTime2 :: Rule+ruleNthTimeOfTime2 = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Time+    , regex "\x7684"+    , dimension Ordinal+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Ordinal od:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNewYearsDay :: Rule+ruleNewYearsDay = Rule+  { name = "new year's day"+  , pattern =+    [ regex "\x5143\x65e6(\x8282|\x7bc0)?"+    ]+  , prod = \_ -> tt $ monthDay 1 1+  }++ruleLastTime :: Rule+ruleLastTime = Rule+  { name = "last <time>"+  , pattern =+    [ regex "\x53bb"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedday6 :: Rule+ruleNamedday6 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x516d|\x5468\x516d|\x793c\x62dc\x516d|\x79ae\x62dc\x516d|\x9031\x516d"+    ]+  , prod = \_ -> tt $ dayOfWeek 6+  }++ruleNamedmonth7 :: Rule+ruleNamedmonth7 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e03\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 7+  }++ruleInDuration :: Rule+ruleInDuration = Rule+  { name = "in <duration>"+  , pattern =+    [ regex "\x518d"+    , dimension Duration+    ]+  , prod = \tokens -> case tokens of+      (_:Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleNow :: Rule+ruleNow = Rule+  { name = "now"+  , pattern =+    [ regex "\x73b0\x5728|\x6b64\x65f6|\x6b64\x523b|\x5f53\x524d|\x73fe\x5728|\x6b64\x6642|\x7576\x524d"+    ]+  , prod = \_ -> tt $ cycleNth TG.Second 0+  }++ruleNationalDay :: Rule+ruleNationalDay = Rule+  { name = "national day"+  , pattern =+    [ regex "(\x56fd\x5e86|\x570b\x6176)(\x8282|\x7bc0)?"+    ]+  , prod = \_ -> tt $ monthDay 10 1+  }++ruleNamedday4 :: Rule+ruleNamedday4 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x56db|\x5468\x56db|\x793c\x62dc\x56db|\x79ae\x62dc\x56db|\x9031\x56db"+    ]+  , prod = \_ -> tt $ dayOfWeek 4+  }++ruleTheCycleAfterTime :: Rule+ruleTheCycleAfterTime = Rule+  { name = "the <cycle> after <time>"+  , pattern =+    [ regex "\x90a3"+    , dimension TimeGrain+    , regex "(\x4e4b)?(\x540e|\x5f8c)"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain 1 td+      _ -> Nothing+  }++ruleTheCycleBeforeTime :: Rule+ruleTheCycleBeforeTime = Rule+  { name = "the <cycle> before <time>"+  , pattern =+    [ regex "\x90a3"+    , dimension TimeGrain+    , regex "(\x4e4b)?\x524d"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_:Token Time td:_) ->+        tt $ cycleNthAfter False grain (-1) td+      _ -> Nothing+  }++ruleNoon :: Rule+ruleNoon = Rule+  { name = "noon"+  , pattern =+    [ regex "\x4e2d\x5348"+    ]+  , prod = \_ -> tt $ hour False 12+  }++ruleToday :: Rule+ruleToday = Rule+  { name = "today"+  , pattern =+    [ regex "\x4eca\x5929"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 0+  }++ruleThisnextDayofweek :: Rule+ruleThisnextDayofweek = Rule+  { name = "this|next <day-of-week>"+  , pattern =+    [ regex "\x4eca|\x660e|\x4e0b(\x4e2a|\x500b)?"+    , Predicate isADayOfWeek+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 True td+      _ -> Nothing+  }++ruleTheDayBeforeYesterday :: Rule+ruleTheDayBeforeYesterday = Rule+  { name = "the day before yesterday"+  , pattern =+    [ regex "\x524d\x5929"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 2+  }++ruleLaborDay :: Rule+ruleLaborDay = Rule+  { name = "labor day"+  , pattern =+    [ regex "\x52b3\x52a8\x8282|\x52de\x52d5\x7bc0"+    ]+  , prod = \_ -> tt $ monthDay 5 1+  }++ruleNextCycle :: Rule+ruleNextCycle = Rule+  { name = "next <cycle>"+  , pattern =+    [ regex "\x4e0b(\x4e2a|\x500b)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 1+      _ -> Nothing+  }++ruleNamedmonth :: Rule+ruleNamedmonth = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e00\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 1+  }++ruleNamedmonth3 :: Rule+ruleNamedmonth3 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e09\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 3+  }++ruleDurationFromNow :: Rule+ruleDurationFromNow = Rule+  { name = "<duration> from now"+  , pattern =+    [ dimension Duration+    , regex "\x540e|\x5f8c"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ inDuration dd+      _ -> Nothing+  }++ruleLastCycle :: Rule+ruleLastCycle = Rule+  { name = "last <cycle>"+  , pattern =+    [ regex "\x4e0a(\x4e2a|\x500b)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt . cycleNth grain $ - 1+      _ -> Nothing+  }++ruleAfternoon :: Rule+ruleAfternoon = Rule+  { name = "afternoon"+  , pattern =+    [ regex "\x4e0b\x5348|\x4e2d\x5348"+    ]+  , prod = \_ ->+      let from = hour False 12+          to = hour False 19+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNamedmonth4 :: Rule+ruleNamedmonth4 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x56db\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 4+  }++ruleMidnight :: Rule+ruleMidnight = Rule+  { name = "midnight"+  , pattern =+    [ regex "\x5348\x591c|\x51cc\x6668"+    ]+  , prod = \_ -> tt $ hour False 0+  }++ruleInduringThePartofday :: Rule+ruleInduringThePartofday = Rule+  { name = "in|during the <part-of-day>"+  , pattern =+    [ Predicate isAPartOfDay+    , regex "\x70b9|\x9ede"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedday5 :: Rule+ruleNamedday5 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x4e94|\x5468\x4e94|\x793c\x62dc\x4e94|\x79ae\x62dc\x4e94|\x9031\x4e94"+    ]+  , prod = \_ -> tt $ dayOfWeek 5+  }++ruleIntersectBy :: Rule+ruleIntersectBy = Rule+  { name = "intersect by \",\""+  , pattern =+    [ Predicate isNotLatent+    , regex ","+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:_:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMmdd :: Rule+ruleMmdd = Rule+  { name = "mm/dd"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do+        m <- parseInt mm+        d <- parseInt dd+        tt $ monthDay m d+      _ -> Nothing+  }++ruleNamedmonth2 :: Rule+ruleNamedmonth2 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e8c\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 2+  }++ruleIntegerLatentTimeofday :: Rule+ruleIntegerLatentTimeofday = Rule+  { name = "<integer> (latent time-of-day)"+  , pattern =+    [ Predicate $ isIntegerBetween 0 23+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ hour True v+      _ -> Nothing+  }++ruleYearNumericWithYearSymbol :: Rule+ruleYearNumericWithYearSymbol = Rule+  { name = "year (numeric with year symbol)"+  , pattern =+    [ Predicate $ isIntegerBetween 1000 9999+    , regex "\x5e74"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt $ year v+      _ -> Nothing+  }++ruleDurationAgo :: Rule+ruleDurationAgo = Rule+  { name = "<duration> ago"+  , pattern =+    [ dimension Duration+    , regex "\x524d"+    ]+  , prod = \tokens -> case tokens of+      (Token Duration dd:_) ->+        tt $ durationAgo dd+      _ -> Nothing+  }++ruleHhmmMilitaryTimeofday :: Rule+ruleHhmmMilitaryTimeofday = Rule+  { name = "hhmm (military time-of-day)"+  , pattern =+    [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do+        h <- parseInt hh+        m <- parseInt mm+        tt . mkLatent $ hourMinute False h m+      _ -> Nothing+  }++ruleLastNCycle :: Rule+ruleLastNCycle = Rule+  { name = "last n <cycle>"+  , pattern =+    [ regex "\x4e0a|\x524d"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain (- v)+      _ -> Nothing+  }++ruleIntersect :: Rule+ruleIntersect = Rule+  { name = "intersect"+  , pattern =+    [ Predicate isNotLatent+    , Predicate isNotLatent+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNamedmonth6 :: Rule+ruleNamedmonth6 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x516d\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 6+  }++ruleNthTimeOfTime :: Rule+ruleNthTimeOfTime = Rule+  { name = "nth <time> of <time>"+  , pattern =+    [ dimension Time+    , dimension Ordinal+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Ordinal od:Token Time td2:_) -> Token Time .+        predNth (TOrdinal.value od - 1) False <$> intersect td2 td1+      _ -> Nothing+  }++ruleNamedmonth8 :: Rule+ruleNamedmonth8 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x516b\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 8+  }++ruleWeekend :: Rule+ruleWeekend = Rule+  { name = "week-end"+  , pattern =+    [ regex "\x5468\x672b|\x9031\x672b"+    ]+  , prod = \_ -> do+      from <- intersect (dayOfWeek 5) (hour False 18)+      to <- intersect (dayOfWeek 1) (hour False 0)+      tt $ interval TTime.Open (from, to)+  }++ruleLastYear :: Rule+ruleLastYear = Rule+  { name = "last year"+  , pattern =+    [ regex "\x53bb\x5e74"+    ]+  , prod = \_ -> tt . cycleNth TG.Year $ - 1+  }++ruleDimTimePartofday :: Rule+ruleDimTimePartofday = Rule+  { name = "<dim time> <part-of-day>"+  , pattern =+    [ dimension Time+    , Predicate isAPartOfDay+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleNextTime :: Rule+ruleNextTime = Rule+  { name = "next <time>"+  , pattern =+    [ regex "\x660e|\x4e0b(\x4e2a|\x500b)?"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 1 False td+      _ -> Nothing+  }++ruleYyyymmdd :: Rule+ruleYyyymmdd = Rule+  { name = "yyyy-mm-dd"+  , pattern =+    [ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleNextNCycle :: Rule+ruleNextNCycle = Rule+  { name = "next n <cycle>"+  , pattern =+    [ regex "\x4e0b|\x540e|\x5f8c"+    , Predicate $ isIntegerBetween 1 9999+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:token:Token TimeGrain grain:_) -> do+        v <- getIntValue token+        tt $ cycleN True grain v+      _ -> Nothing+  }++ruleMorning :: Rule+ruleMorning = Rule+  { name = "morning"+  , pattern =+    [ regex "\x65e9\x4e0a|\x65e9\x6668"+    ]+  , prod = \_ ->+      let from = hour False 4+          to = hour False 12+      in tt . mkLatent . partOfDay $+           interval TTime.Open (from, to)+  }++ruleNextYear :: Rule+ruleNextYear = Rule+  { name = "next year"+  , pattern =+    [ regex "\x660e\x5e74"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 1+  }++ruleThisCycle :: Rule+ruleThisCycle = Rule+  { name = "this <cycle>"+  , pattern =+    [ regex "(\x8fd9|\x9019)(\x4e00)?"+    , dimension TimeGrain+    ]+  , prod = \tokens -> case tokens of+      (_:Token TimeGrain grain:_) ->+        tt $ cycleNth grain 0+      _ -> Nothing+  }++ruleThisTime :: Rule+ruleThisTime = Rule+  { name = "this <time>"+  , pattern =+    [ regex "\x4eca|\x8fd9|\x9019"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth 0 False td+      _ -> Nothing+  }++ruleYesterday :: Rule+ruleYesterday = Rule+  { name = "yesterday"+  , pattern =+    [ regex "\x6628\x5929"+    ]+  , prod = \_ -> tt . cycleNth TG.Day $ - 1+  }++ruleChristmas :: Rule+ruleChristmas = Rule+  { name = "christmas"+  , pattern =+    [ regex "(\x5723\x8bde|\x8056\x8a95)(\x8282|\x7bc0)?"+    ]+  , prod = \_ -> tt $ monthDay 12 25+  }++ruleLastNight :: Rule+ruleLastNight = Rule+  { name = "last night"+  , pattern =+    [ regex "\x6628\x665a|\x6628\x5929\x665a\x4e0a"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day $ - 1+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleTimeofdayAmpm :: Rule+ruleTimeofdayAmpm = Rule+  { name = "<time-of-day> am|pm"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "([ap])(\\s|\\.)?m?\\.?"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->+        tt . timeOfDayAMPM td $ Text.toLower ap == "a"+      _ -> Nothing+  }++ruleArmysDay :: Rule+ruleArmysDay = Rule+  { name = "army's day"+  , pattern =+    [ regex "\x5efa(\x519b\x8282|\x8ecd\x7bc0)"+    ]+  , prod = \_ -> tt $ monthDay 8 1+  }++ruleNamedmonthDayofmonth :: Rule+ruleNamedmonthDayofmonth = Rule+  { name = "<named-month> <day-of-month>"+  , pattern =+    [ Predicate isAMonth+    , dimension Numeral+    , regex "\x53f7|\x865f|\x65e5"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:token:_) -> Token Time <$> intersectDOM td token+      _ -> Nothing+  }++ruleLastTuesdayLastJuly :: Rule+ruleLastTuesdayLastJuly = Rule+  { name = "last tuesday, last july"+  , pattern =+    [ regex "\x4e0a"+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (_:Token Time td:_) ->+        tt $ predNth (-1) False td+      _ -> Nothing+  }++ruleNamedmonth5 :: Rule+ruleNamedmonth5 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e94\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 5+  }++ruleNamedday7 :: Rule+ruleNamedday7 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x65e5|\x661f\x671f\x5929|\x793c\x62dc\x5929|\x5468\x65e5|\x79ae\x62dc\x5929|\x9031\x65e5"+    ]+  , prod = \_ -> tt $ dayOfWeek 7+  }++rulePartofdayDimTime :: Rule+rulePartofdayDimTime = Rule+  { name = "<part-of-day> <dim time>"+  , pattern =+    [ Predicate isAPartOfDay+    , dimension Time+    ]+  , prod = \tokens -> case tokens of+      (Token Time td1:Token Time td2:_) ->+        Token Time <$> intersect td1 td2+      _ -> Nothing+  }++ruleMonthNumericWithMonthSymbol :: Rule+ruleMonthNumericWithMonthSymbol = Rule+  { name = "month (numeric with month symbol)"+  , pattern =+    [ Predicate $ isIntegerBetween 1 12+    , regex "\x6708"+    ]+  , prod = \tokens -> case tokens of+      (token:_) -> do+        v <- getIntValue token+        tt . mkLatent $ month v+      _ -> Nothing+  }++ruleTonight :: Rule+ruleTonight = Rule+  { name = "tonight"+  , pattern =+    [ regex "\x4eca\x665a|\x4eca\x5929\x665a\x4e0a"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 0+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleTomorrowNight :: Rule+ruleTomorrowNight = Rule+  { name = "tomorrow night"+  , pattern =+    [ regex "\x660e\x665a|\x660e\x5929\x665a\x4e0a"+    ]+  , prod = \_ ->+      let td1 = cycleNth TG.Day 1+          td2 = interval TTime.Open (hour False 18, hour False 0)+      in Token Time . partOfDay <$> intersect td1 td2+  }++ruleNamedmonth10 :: Rule+ruleNamedmonth10 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x5341\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 10+  }++ruleChildrensDay :: Rule+ruleChildrensDay = Rule+  { name = "children's day"+  , pattern =+    [ regex "(\x513f|\x5152)\x7ae5(\x8282|\x7bc0)"+    ]+  , prod = \_ -> tt $ monthDay 6 1+  }++ruleThisYear :: Rule+ruleThisYear = Rule+  { name = "this year"+  , pattern =+    [ regex "\x4eca\x5e74"+    ]+  , prod = \_ -> tt $ cycleNth TG.Year 0+  }++ruleAbsorptionOfAfterNamedDay :: Rule+ruleAbsorptionOfAfterNamedDay = Rule+  { name = "absorption of , after named day"+  , pattern =+    [ Predicate isADayOfWeek+    , regex ","+    ]+  , prod = \tokens -> case tokens of+      (x:_) -> Just x+      _ -> Nothing+  }++ruleNamedmonth11 :: Rule+ruleNamedmonth11 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x5341\x4e00\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 11+  }++ruleWomensDay :: Rule+ruleWomensDay = Rule+  { name = "women's day"+  , pattern =+    [ regex "(\x5987|\x5a66)\x5973(\x8282|\x7bc0)"+    ]+  , prod = \_ -> tt $ monthDay 3 8+  }++ruleEveningnight :: Rule+ruleEveningnight = Rule+  { name = "evening|night"+  , pattern =+    [ regex "\x665a\x4e0a|\x665a\x95f4"+    ]+  , prod = \_ ->+      let from = hour False 18+          to = hour False 0+      in tt . partOfDay . mkLatent $+           interval TTime.Open (from, to)+  }++ruleNamedday3 :: Rule+ruleNamedday3 = Rule+  { name = "named-day"+  , pattern =+    [ regex "\x661f\x671f\x4e09|\x5468\x4e09|\x793c\x62dc\x4e09|\x79ae\x62dc\x4e09|\x9031\x4e09"+    ]+  , prod = \_ -> tt $ dayOfWeek 3+  }++ruleMmddyyyy :: Rule+ruleMmddyyyy = Rule+  { name = "mm/dd/yyyy"+  , pattern =+    [ regex "(0?[1-9]|1[0-2])/(3[01]|[12]\\d|0?[1-9])/(\\d{2,4})"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do+        y <- parseInt yy+        m <- parseInt mm+        d <- parseInt dd+        tt $ yearMonthDay y m d+      _ -> Nothing+  }++ruleTomorrow :: Rule+ruleTomorrow = Rule+  { name = "tomorrow"+  , pattern =+    [ regex "\x660e\x5929"+    ]+  , prod = \_ -> tt $ cycleNth TG.Day 1+  }++ruleTimeofdayOclock :: Rule+ruleTimeofdayOclock = Rule+  { name = "<time-of-day> o'clock"+  , pattern =+    [ Predicate isATimeOfDay+    , regex "\x9ede|\x70b9"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:_) ->+        tt $ notLatent td+      _ -> Nothing+  }++ruleNamedmonth9 :: Rule+ruleNamedmonth9 = Rule+  { name = "named-month"+  , pattern =+    [ regex "\x4e5d\x6708(\x4efd)?"+    ]+  , prod = \_ -> tt $ month 9+  }++ruleTimezone :: Rule+ruleTimezone = Rule+  { name = "<time> timezone"+  , pattern =+    [ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent+    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"+    ]+  , prod = \tokens -> case tokens of+      (Token Time td:+       Token RegexMatch (GroupMatch (tz:_)):+       _) -> Token Time <$> inTimezone tz td+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleAbsorptionOfAfterNamedDay+  , ruleAfternoon+  , ruleArmysDay+  , ruleChildrensDay+  , ruleChristmas+  , ruleDimTimePartofday+  , ruleDurationAgo+  , ruleDurationFromNow+  , ruleEveningnight+  , ruleHhmmMilitaryTimeofday+  , ruleHhmmTimeofday+  , ruleInDuration+  , ruleInduringThePartofday+  , ruleIntegerLatentTimeofday+  , ruleIntersect+  , ruleIntersectBy+  , ruleLaborDay+  , ruleLastCycle+  , ruleLastNCycle+  , ruleLastNight+  , ruleLastTime+  , ruleLastTuesdayLastJuly+  , ruleLastYear+  , ruleMidnight+  , ruleMmdd+  , ruleMmddyyyy+  , ruleMonthNumericWithMonthSymbol+  , ruleMorning+  , ruleNamedday+  , ruleNamedday2+  , ruleNamedday3+  , ruleNamedday4+  , ruleNamedday5+  , ruleNamedday6+  , ruleNamedday7+  , ruleNamedmonth+  , ruleNamedmonth10+  , ruleNamedmonth11+  , ruleNamedmonth12+  , ruleNamedmonth2+  , ruleNamedmonth3+  , ruleNamedmonth4+  , ruleNamedmonth5+  , ruleNamedmonth6+  , ruleNamedmonth7+  , ruleNamedmonth8+  , ruleNamedmonth9+  , ruleNamedmonthDayofmonth+  , ruleNationalDay+  , ruleNewYearsDay+  , ruleNextCycle+  , ruleNextNCycle+  , ruleNextTime+  , ruleNextYear+  , ruleNoon+  , ruleNow+  , ruleNthTimeOfTime+  , ruleNthTimeOfTime2+  , rulePartofdayDimTime+  , ruleRelativeMinutesAfterpastIntegerHourofday+  , ruleRelativeMinutesAfterpastNoonmidnight+  , ruleRelativeMinutesTotillbeforeIntegerHourofday+  , ruleRelativeMinutesTotillbeforeNoonmidnight+  , ruleQuarterAfterpastIntegerHourofday+  , ruleQuarterAfterpastNoonmidnight+  , ruleQuarterTotillbeforeIntegerHourofday+  , ruleQuarterTotillbeforeNoonmidnight+  , ruleHalfAfterpastIntegerHourofday+  , ruleHalfAfterpastNoonmidnight+  , ruleHalfTotillbeforeIntegerHourofday+  , ruleHalfTotillbeforeNoonmidnight+  , ruleTheCycleAfterTime+  , ruleTheCycleBeforeTime+  , ruleTheDayAfterTomorrow+  , ruleTheDayBeforeYesterday+  , ruleThisCycle+  , ruleThisDayofweek+  , ruleThisTime+  , ruleThisYear+  , ruleThisnextDayofweek+  , ruleTimeofdayAmpm+  , ruleTimeofdayOclock+  , ruleToday+  , ruleTomorrow+  , ruleTomorrowNight+  , ruleTonight+  , ruleValentinesDay+  , ruleWeekend+  , ruleWomensDay+  , ruleYearNumericWithYearSymbol+  , ruleYesterday+  , ruleYyyymmdd+  , ruleTimezone+  ]
+ Duckling/TimeGrain/DA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.DA.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sekund(er)?", TG.Second)+         , ("minute (grain)", "minut(ter)?", TG.Minute)+         , ("hour (grain)", "t(imer?)?", TG.Hour)+         , ("day (grain)", "dag(e)?", TG.Day)+         , ("week (grain)", "uger?", TG.Week)+         , ("month (grain)", "m\x00e5ned(er)?", TG.Month)+         , ("quarter (grain)", "kvartal(er)?", TG.Quarter)+         , ("year (grain)", "\x00e5r", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.DE.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sekunden?", TG.Second)+         , ("minute (grain)", "minuten?", TG.Minute)+         , ("hour (grain)", "stunden?", TG.Hour)+         , ("day (grain)", "tage?n?", TG.Day)+         , ("week (grain)", "wochen?", TG.Week)+         , ("month (grain)", "monate?n?", TG.Month)+         , ("quarter (grain)", "quartale?", TG.Quarter)+         , ("year (grain)", "jahre?n?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/EN/Rules.hs view
@@ -0,0 +1,40 @@+-- 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.TimeGrain.EN.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain) ", "sec(ond)?s?",      TG.Second)+         , ("minute (grain)" , "min(ute)?s?",      TG.Minute)+         , ("hour (grain)"   , "h(((ou)?rs?)|r)?", TG.Hour)+         , ("day (grain)"    , "days?",            TG.Day)+         , ("week (grain)"   , "weeks?",           TG.Week)+         , ("month (grain)"  , "months?",          TG.Month)+         , ("quarter (grain)", "(quarter|qtr)s?",        TG.Quarter)+         , ("year (grain)"   , "y(ea)?rs?",           TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/ES/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.ES.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("segundo (grain)", "seg(undo)?s?", TG.Second)+         , ("minutos (grain)", "min(uto)?s?", TG.Minute)+         , ("hora (grain)", "h(ora)?s?", TG.Hour)+         , ("dia (grain)", "d(\x00ed|i)as?", TG.Day)+         , ("semana (grain)", "semanas?", TG.Week)+         , ("mes (grain)", "mes(es)?", TG.Month)+         , ("trimestre (grain)", "trimestres?", TG.Quarter)+         , ("año (grain)", "a(n|\x00f1)os?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/FR/Rules.hs view
@@ -0,0 +1,40 @@+-- 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.TimeGrain.FR.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("seconde (grain)", "sec(onde)?s?", TG.Second)+         , ("minute (grain)", "min(ute)?s?", TG.Minute)+         , ("heure (grain)", "heures?", TG.Hour)+         , ("jour (grain)", "jour(n(e|\x00e9)e?)?s?", TG.Day)+         , ("semaine (grain)", "semaines?", TG.Week)+         , ("mois (grain)", "mois", TG.Month)+         , ("trimestre (grain)", "trimestres?", TG.Quarter)+         , ("année (grain)", "an(n(e|\x00e9)e?)?s?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/GA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.GA.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("soicind (grain)", "t?sh?oicind(\x00ed|i)?", TG.Second)+         , ("nóiméad (grain)", "n[\x00f3o]im(\x00e9|e)[ai]da?", TG.Minute)+         , ("uair (grain)", "([thn]-?)?uair(e|eanta)?", TG.Hour)+         , ("lá (grain)", "l(ae(thanta)?|(\x00e1|a))", TG.Day)+         , ("seachtain (grain)", "t?sh?eachtain(e|(\x00ed|i))?", TG.Week)+         , ("mí (grain)", "mh?(\x00ed|i)(sa|nna)", TG.Month)+         , ("ráithe (grain)", "r(\x00e1|a)ith(e|(\x00ed|i))", TG.Quarter)+         , ("bliain (grain)", "m?bh?lia(in|na|nta)", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/HE/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.HE.Rules+  ( rules ) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.TimeGrain.Types as TG++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "\x05e9\x05e0\x05d9\x05d5\x05ea|\x05e9\x05e0\x05d9\x05d9\x05d4", TG.Second)+         , ("minute (grain)", "\x05d3\x05e7\x05d4|\x05d3\x05e7\x05d5\x05ea", TG.Minute)+         , ("hour (grain)", "\x05e9\x05e2\x05d5\x05ea|\x05e9\x05e2\x05d4", TG.Hour)+         , ("day (grain)", "\x05d9\x05de\x05d9\x05dd|\x05d9\x05d5\x05dd", TG.Day)+         , ("week (grain)", "\x05e9\x05d1\x05d5\x05e2|\x05e9\x05d1\x05d5\x05e2\x05d5\x05ea", TG.Week)+         , ("month (grain)", "\x05d7\x05d5\x05d3\x05e9|\x05d7\x05d5\x05d3\x05e9\x05d9\x05dd", TG.Month)+         , ("quarter (grain)", "\x05e8\x05d1\x05e2", TG.Quarter)+         , ("year (grain)", "\x05e9\x05e0\x05d4", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/HR/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.HR.Rules+  ( rules ) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.TimeGrain.Types as TG++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sek(und)?(a|e|u)?", TG.Second)+         , ("minute (grain)", "min(ut)?(a|e|u)?", TG.Minute)+         , ("hour (grain)", "h|sat(i|a|e)?", TG.Hour)+         , ("day (grain)", "dan(i|a|e)?", TG.Day)+         , ("week (grain)", "tjeda?n(a|e|u|i)?", TG.Week)+         , ("month (grain)", "mjesec(a|e|u|i)?", TG.Month)+         , ("quarter (grain)", "kvartalu?|tromjese(c|\x010d)j(e|u)", TG.Quarter)+         , ("year (grain)", "godin(a|e|u)", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/IT/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.IT.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("seconde (grain)", "second[oi]", TG.Second)+         , ("minute (grain)", "minut[oi]", TG.Minute)+         , ("heure (grain)", "or[ae]", TG.Hour)+         , ("jour (grain)", "giorn[oi]", TG.Day)+         , ("semaine (grain)", "settiman[ae]", TG.Week)+         , ("mois (grain)", "mes[ei]", TG.Month)+         , ("trimestre (grain)", "trimestr[ei]", TG.Quarter)+         , ("année (grain)", "ann?[oi]", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/JA/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.JA.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "\x79d2(\x6bce|\x9593)?", TG.Second)+         , ("minute (grain)", "\x5206(\x6bce|\x9593)?", TG.Minute)+         , ("hour (grain)", "\x6642(\x6bce|\x9593)?", TG.Hour)+         , ("day (grain)", "\x65e5(\x6bce|\x9593)?", TG.Day)+         , ("week (grain)", "\x9031(\x6bce|\x9593)?", TG.Week)+         , ("month (grain)", "\x6708(\x6bce|\x9593)?", TG.Month)+         , ("year (grain)", "\x5e74(\x6bce|\x9593)?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/KO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.KO.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "\xcd08", TG.Second)+         , ("minute (grain)", "\xbd84", TG.Minute)+         , ("hour (grain)", "\xc2dc(\xac04)?", TG.Hour)+         , ("day (grain)", "\xb0a0|\xc77c(\xac04|\xb3d9\xc548)?", TG.Day)+         , ("week (grain)", "\xc8fc(\xac04|\xb3d9\xc548|\xc77c)?", TG.Week)+         , ("month (grain)", "(\xb2ec)(\xac04|\xb3d9\xc548)?", TG.Month)+         , ("quarter (grain)", "\xbd84\xae30(\xac04|\xb3d9\xc548)?", TG.Quarter)+         , ("year (grain)", "\xd574|\xc5f0\xac04|\xb144(\xac04|\xb3d9\xc548)?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/NB/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.NB.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sek(und(er)?)?", TG.Second)+         , ("minute (grain)", "min(utt(er)?)?", TG.Minute)+         , ("hour (grain)", "t(ime(r)?)?", TG.Hour)+         , ("day (grain)", "dag(er)?", TG.Day)+         , ("week (grain)", "uke(r|n)?", TG.Week)+         , ("month (grain)", "m\x00e5ned(er)?", TG.Month)+         , ("quarter (grain)", "kvart(al|er)(et)?", TG.Quarter)+         , ("year (grain)", "\x00e5r", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/PL/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.PL.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sekund(y|zie|(e|\x0119)|om|ami|ach|o|a)?|s", TG.Second)+         , ("minute (grain)", "minut(y|cie|(e|\x0119)|om|o|ami|ach|(a|\x0105))?|m", TG.Minute)+         , ("hour (grain)", "h|godzin(y|(e|\x0119)|ie|om|o|ami|ach|(a|\x0105))?", TG.Hour)+         , ("day (grain)", "dzie(n|\x0144|ni(a|\x0105))|dni(owi|ach|a|\x0105)?", TG.Day)+         , ("week (grain)", "tydzie(n|\x0144|)|tygod(ni(owi|u|a|em))|tygodn(iach|iami|iom|ie|i)|tyg\\.?", TG.Week)+         , ("month (grain)", "miesi(a|\x0105)c(owi|em|u|e|om|ami|ach|a)?", TG.Month)+         , ("quarter (grain)", "kwarta(l|\x0142)(u|owi|em|e|(o|\x00f3)w|om|ach|ami|y)?", TG.Quarter)+         , ("year (grain)", "rok(u|owi|iem)?|lat(ami|ach|a|om)?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/PT/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.PT.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("segundo (grain)", "seg(undo)?s?", TG.Second)+         , ("minutos (grain)", "min(uto)?s?", TG.Minute)+         , ("hora (grain)", "h(ora)?s?", TG.Hour)+         , ("dia (grain)", "d(\x00ed|i)as?", TG.Day)+         , ("semana (grain)", "semanas?", TG.Week)+         , ("mes (grain)", "m(e|\x00ea)s(es)?", TG.Month)+         , ("ano (grain)", "anos?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/RO/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.RO.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("secunde (grain)", "sec(und(a|e|\x0103))?", TG.Second)+         , ("minute (grain)", "min(ut(e|ul)?)?", TG.Minute)+         , ("ore (grain)", "h|or(a|e(le)?|\x0103)", TG.Hour)+         , ("zile (grain)", "zi(le(le)?|u(a|\x0103))?", TG.Day)+         , ("saptamani (grain)", "sapt(a|\x0103)m(a|\x00e2)n(ile|a|\x0103|i)", TG.Week)+         , ("luni (grain)", "lun(i(le)?|a|\x0103)", TG.Month)+         , ("trimestru (grain)", "trimestr(e(le)?|ul?)", TG.Quarter)+         , ("ani (grain)", "an(ul|ii?)?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/SV/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.TimeGrain.SV.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "sek(und(er(na)?)?)?", TG.Second)+         , ("minute (grain)", "min(ut(er(na)?)?)?", TG.Minute)+         , ("hour (grain)", "t(imm(e(n)?|ar(na)?)?)?", TG.Hour)+         , ("day (grain)", "dag(en|ar(na)?)?", TG.Day)+         , ("week (grain)", "veck(or(na)?|a(n)?)?", TG.Week)+         , ("month (grain)", "m\x00e5nad(er(na)?)?", TG.Month)+         , ("quarter (grain)", "kvart(al)(et)?", TG.Quarter)+         , ("year (grain)", "\x00e5r(en)?", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/Types.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.TimeGrain.Types+  ( Grain(..)+  , add+  , inSeconds+  )+  where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import qualified Data.Text as Text+import Data.Text.Lazy.Builder (fromText)+import qualified Data.Time as Time+import GHC.Generics+import TextShow++import Prelude++import Duckling.Resolve (Resolve(..))++data Grain = Second | Minute | Hour | Day | Week | Month | Quarter | Year+  deriving (Eq, Generic, Hashable, Ord, Bounded, Enum, Show, NFData)++instance Resolve Grain where+  type ResolvedValue Grain = Grain+  resolve _ _ = Nothing++instance TextShow Grain where+  showb = fromText . Text.toLower . Text.pack . show++instance ToJSON Grain where+  toJSON = String . showt++updateUTCDay :: Time.UTCTime -> (Time.Day -> Time.Day) -> Time.UTCTime+updateUTCDay (Time.UTCTime day diffTime) f = Time.UTCTime (f day) diffTime++add :: Time.UTCTime -> Grain -> Integer -> Time.UTCTime+add utcTime Second n = Time.addUTCTime (realToFrac n) utcTime+add utcTime Minute n = Time.addUTCTime (realToFrac $ 60 * n) utcTime+add utcTime Hour n = Time.addUTCTime (realToFrac $ 3600 * n) utcTime+add utcTime Day n = updateUTCDay utcTime $ Time.addDays n+add utcTime Week n = updateUTCDay utcTime . Time.addDays $ 7 * n+add utcTime Month n = updateUTCDay utcTime $ Time.addGregorianMonthsClip n+add utcTime Quarter n =+  updateUTCDay utcTime . Time.addGregorianMonthsClip $ 3 * n+add utcTime Year n = updateUTCDay utcTime $ Time.addGregorianYearsClip n++inSeconds :: Grain -> Int -> Int+inSeconds Second  n = n+inSeconds Minute  n = n * 60+inSeconds Hour    n = n * inSeconds Minute 60+inSeconds Day     n = n * inSeconds Hour 24+inSeconds Week    n = n * inSeconds Day 7+inSeconds Month   n = n * inSeconds Day 30+inSeconds Quarter n = n * inSeconds Month 3+inSeconds Year    n = n * inSeconds Day 365
+ Duckling/TimeGrain/VI/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.VI.Rules+  ( rules ) where++import Data.String+import Data.Text (Text)+import Prelude++import Duckling.Dimensions.Types+import Duckling.Types+import qualified Duckling.TimeGrain.Types as TG++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "(gi\x00e2y|s|sec)", TG.Second)+         , ("minute (grain)", "(ph\x00fat|m|min)", TG.Minute)+         , ("hour (grain)", "(gi\x1edd|h|ti\x1ebfng)", TG.Hour)+         , ("day (grain)", "ng\x00e0y", TG.Day)+         , ("week (grain)", "tu\x1ea7n", TG.Week)+         , ("month (grain)", "th\x00e1ng", TG.Month)+         , ("quarter (grain)", "qu\x00fd", TG.Quarter)+         , ("year (grain)", "n\x0103m", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/TimeGrain/ZH/Rules.hs view
@@ -0,0 +1,40 @@+-- 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 #-}++module Duckling.TimeGrain.ZH.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import qualified Duckling.TimeGrain.Types as TG+import Duckling.Types++grains :: [(Text, String, TG.Grain)]+grains = [ ("second (grain)", "\x79d2(\x949f|\x9418)?", TG.Second)+         , ("minute (grain)", "\x5206(\x949f|\x9418)?", TG.Minute)+         , ("hour (grain)", "\x5c0f\x65f6|\x5c0f\x6642", TG.Hour)+         , ("day (grain)", "\x5929", TG.Day)+         , ("week (grain)", "\x5468|\x9031|\x793c\x62dc|\x79ae\x62dc", TG.Week)+         , ("month (grain)", "\x6708", TG.Month)+         , ("year (grain)", "\x5e74", TG.Year)+         ]++rules :: [Rule]+rules = map go grains+  where+    go (name, regexPattern, grain) = Rule+      { name = name+      , pattern = [regex regexPattern]+      , prod = \_ -> Just $ Token TimeGrain grain+      }
+ Duckling/Types.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}++module Duckling.Types where++import Control.DeepSeq+import Data.Aeson+import qualified Data.ByteString.Lazy as LB+import Data.GADT.Compare+import Data.Hashable+import Data.Maybe+import Data.String+import Data.Text (Text)+import qualified Data.Text.Encoding as Text+import Data.Typeable ((:~:)(Refl), Typeable)+import GHC.Generics+import Prelude+import qualified Text.Regex.Base as R+import qualified Text.Regex.PCRE as PCRE++import Duckling.Dimensions.Types+import Duckling.Resolve++-- -----------------------------------------------------------------+-- Token++data Token = forall a . (Resolve a, Eq a, Hashable a, Show a, NFData a) =>+  Token (Dimension a) a++deriving instance Show Token+instance Eq Token where+  Token d1 v1 == Token d2 v2 = case geq d1 d2 of+    Just Refl -> v1 == v2+    Nothing   -> False++instance Hashable Token where+  hashWithSalt s (Token dim v) = hashWithSalt s (dim, v)++instance NFData Token where+  rnf (Token _ v) = rnf v++isDimension :: Dimension a -> Token -> Bool+isDimension dim (Token dim' _) = isJust $ geq dim dim'++data Node = Node+  { nodeRange :: Range+  , token     :: Token+  , children  :: [Node]+  , rule      :: Maybe Text+  } deriving (Eq, Generic, Hashable, Show, NFData)++data ResolvedToken = Resolved+  { range :: Range+  , node :: Node+  , jsonValue :: Value+  } deriving (Eq, Show)++instance Ord ResolvedToken where+  compare (Resolved range1 _ json1) (Resolved range2 _ json2) =+    case compare range1 range2 of+      EQ -> compare (toJText json1) (toJText json2)+      z  -> z++data Candidate = Candidate ResolvedToken Double Bool+  deriving (Eq, Show)++instance Ord Candidate where+  compare (Candidate (Resolved{range = Range s1 e1, node = Node{token = Token d1 _}}) score1 t1)+          (Candidate (Resolved{range = Range s2 e2, node = Node{token = tok2}}) score2 t2)+    | isDimension d1 tok2 = case starts of+        EQ -> case ends of+          EQ -> compare score1 score2+          z -> z+        LT -> case ends of+          LT -> EQ+          _ -> GT+        GT -> case ends of+          GT -> EQ+          _ -> LT+    | t1 == t2 = compRange+    | t1 && compRange == GT = GT+    | t2 && compRange == LT = LT+    | otherwise = EQ+      where+        starts = compare s1 s2+        ends = compare e1 e2+        -- a > b if a recovers b+        compRange = case starts of+          EQ -> ends+          LT -> case ends of+            LT -> EQ+            _  -> GT+          GT -> case ends of+            GT -> EQ+            _  -> LT++data Range = Range Int Int+  deriving (Eq, Ord, Generic, Hashable, Show, NFData)++type Production = [Token] -> Maybe Token+type Predicate = Token -> Bool+data PatternItem = Regex PCRE.Regex | Predicate Predicate++type Pattern = [PatternItem]++data Rule = Rule+  { name :: Text+  , pattern :: Pattern+  , prod :: Production+  }++instance Show Rule where+  show (Rule name _ _) = show name++data Entity = Entity+  { dim   :: Text+  , body  :: Text+  , value :: Text+  , start :: Int+  , end   :: Int+  } deriving (Eq, Generic, Show, NFData)++instance ToJSON Entity where+  toEncoding = genericToEncoding defaultOptions++toJText :: ToJSON x => x -> Text+toJText j = Text.decodeUtf8 $ LB.toStrict $ encode j++-- -----------------------------------------------------------------+-- Predicates helpers++regex :: String -> PatternItem+regex = Regex . R.makeRegexOpts compOpts execOpts+  where+    compOpts = PCRE.defaultCompOpt + PCRE.compCaseless+    execOpts = PCRE.defaultExecOpt++dimension :: Typeable a => Dimension a -> PatternItem+dimension value = Predicate $ isDimension value
+ Duckling/Types/Document.hs view
@@ -0,0 +1,199 @@+-- 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 BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards #-}++module Duckling.Types.Document+  ( Document -- abstract+  , fromText+  , (!)+  , length+  , byteStringFromPos+  , isAdjacent+  , isRangeValid+  ) where++import qualified Data.Array.Unboxed as Array+import Data.Array.Unboxed (UArray)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import qualified Data.Char as Char+import Data.List (scanl', foldl', foldr)+import Data.String+import Data.Text (Text)+import qualified Data.Text.Unsafe as UText+import qualified Data.Text.Encoding as Text+import qualified Data.Text as Text+import qualified Data.Text.Internal.Unsafe.Char as UText+import Prelude hiding (length)+++data Document = Document+  { rawInput :: !Text+  , utf8Encoded :: ByteString+  , indexable :: UArray Int Char -- for O(1) indexing pos -> Char+  , firstNonAdjacent :: UArray Int Int+    -- for a given index 'i' it keeps a first index 'j' greater or equal 'i'+    -- such that isAdjacentSeparator (indexable ! j) == False+    -- eg. " a document " :: Document+    --     firstNonAdjacent = [1,1,3,3,4,5,6,7,8,9,10,12]+    -- Note that in this case 12 is the length of the vector, hence not a+    -- valid index inside the array, this is intentional.+  , tDropToBSDrop :: UArray Int Int+    -- how many bytes to BS.drop from a utf8 encoded ByteString to+    -- reach the same position as Text.drop would+  , bsDropToTDrop :: UArray Int Int+    -- the inverse of tDropToBSDrop, rounds down for bytes that are+    -- not on character boundary+    -- for "żółty" :: Document+    --   tDropToBSDrop = [0,2,4,6,7,8]+    --   bsDropToTDrop = [0,1,1,2,2,3,3,4,5]+    --   tDropToUtf16Drop = [0,1,2,3,4,5]+  , tDropToUtf16Drop :: UArray Int Int+    -- translate Text.drop to Data.Text.Unsafe.dropWord16+  } deriving (Show)++{-+Note [Regular expressions and Text]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Text is UTF-16 encoded internally and PCRE operates on UTF-8 encoded+ByteStrings. Because we do a lot of regexp matching on the same Text,+it pays off to cache UTF-8 the encoded ByteString. That's the utf8Ecoded+field in Document.++Moreover we do regexp matching with capture, where the captured groups+are returned as ByteString and we want them as Text. But all of the+captured groups are just a substrings of the original Text.+Fortunately PCRE has an API that returns a MatchArray - a structure with+just the ByteString indices and ByteString lengths of the matched fragments.+If we play with indices right we can translate them to offsets into the+original Text, share the underlying Text buffer and avoid all of+UTF-8 and UTF-16 encoding and new ByteString and Text allocation.+-}++instance IsString Document where+  fromString = fromText . fromString++fromText :: Text -> Document+fromText rawInput = Document{..}+  where+  utf8Encoded = Text.encodeUtf8 rawInput+  rawInputLength = Text.length rawInput+  unpacked = Text.unpack rawInput+  indexable = Array.listArray (0, rawInputLength - 1) unpacked+  firstNonAdjacent = Array.listArray (0, rawInputLength - 1) $ snd $+   foldr gen (rawInputLength, []) $ zip [0..] unpacked+  -- go from the end keeping track of the first nonAdjacent (best)+  gen (ix, elem) (best, !acc)+    | isAdjacentSeparator elem = (best, best:acc)+    | otherwise = (ix, ix:acc)+  tDropToBSDropList = scanl' (\acc a -> acc + utf8CharWidth a) 0 unpacked+  tDropToBSDrop = Array.listArray (0, rawInputLength) tDropToBSDropList+  tDropToUtf16Drop = Array.listArray (0, rawInputLength) $+    scanl' (\acc a -> acc + utf16CharWidth a) 0 unpacked+  bsDropToTDrop = Array.listArray (0, BS.length utf8Encoded) $+    reverse $ snd $ foldl' fun (-1, []) $ zip [0..] tDropToBSDropList+  fun (lastPos, !acc) (ix, elem) = (elem, replicate (elem - lastPos) ix ++ acc)+  utf8CharWidth c+    | w <= 0x7F = 1+    | w <= 0x7FF = 2+    | w <= 0xFFFF = 3+    | otherwise = 4+    where+    w = UText.ord c+  utf16CharWidth c+    | w < 0x10000 = 1+    | otherwise = 2+    where+    w = UText.ord c++-- As regexes are matched without whitespace delimitator, we need to check+-- the reasonability of the match to actually be a word.+isRangeValid :: Document -> Int -> Int -> Bool+isRangeValid doc start end =+  (start == 0 ||+      isDifferent (doc ! (start - 1)) (doc ! start)) &&+  (end == length doc ||+      isDifferent (doc ! (end - 1)) (doc ! end))+  where+    charClass :: Char -> Char+    charClass c+      | Char.isLower c = 'l'+      | Char.isUpper c = 'u'+      | Char.isDigit c = 'd'+      | otherwise = c+    isDifferent :: Char -> Char -> Bool+    isDifferent a b = charClass a /= charClass b++-- True iff a is followed by whitespaces and b.+isAdjacent :: Document -> Int -> Int -> Bool+isAdjacent Document{..} a b =+  b >= a && (firstNonAdjacent Array.! a >= b)++isAdjacentSeparator :: Char -> Bool+isAdjacentSeparator c = elem c [' ', '\t', '-']++(!) :: Document -> Int -> Char+(!) Document { indexable = s } ix = s Array.! ix++length :: Document -> Int+length Document { indexable = s } = Array.rangeSize $ Array.bounds s++-- | Given a document and an offset (think Text.drop offset),+-- returns a utf8 encoded substring of Document at that offset+-- and 2 translation functions:+--   rangeToText - given a range in the returned ByteString, gives+--     a corresponding subrange of the Document as Text+--   translateRange - given a start and a length of a range in the returned+--     ByteString, gives a corresponding subrange in the Document as pair+--     of (start, end) of Text.drop offsets+{-# INLINE byteStringFromPos #-}+-- if we don't inline we seem to pay for the tuple, there might be+-- an easier way+byteStringFromPos+  :: Document+  -> Int+  -> ( ByteString+     , (Int, Int) -> Text+     , Int -> Int -> (Int, Int)+     )+byteStringFromPos+  Document { rawInput = rawInput+           , utf8Encoded = utf8Encoded+           , tDropToBSDrop = tDropToBSDrop+           , bsDropToTDrop = bsDropToTDrop+           , tDropToUtf16Drop = tDropToUtf16Drop+           }+  position = (substring, rangeToText, translateRange)+  where+  -- See Note [Regular expressions and Text] to understand what's going+  -- on here+  utf8Position = tDropToBSDrop Array.! position+  substring :: ByteString+  substring = BS.drop utf8Position utf8Encoded+  -- get a subrange of Text reusing the underlying buffer using+  -- utf16 start and end positions+  rangeToText :: (Int, Int) -> Text+  rangeToText (-1, _) = ""+  -- this is what regexec from Text.Regex.PCRE.ByteString does+  rangeToText r = UText.takeWord16 (end16Pos - start16Pos) $+    UText.dropWord16 start16Pos rawInput+    where+    start16Pos = tDropToUtf16Drop Array.! startPos+    end16Pos = tDropToUtf16Drop Array.! endPos+    (startPos, endPos) = uncurry translateRange r+  -- from utf8 offset and length to Text character start and end position+  translateRange :: Int -> Int -> (Int, Int)+  translateRange !bsStart !bsLen = startPos `seq` endPos `seq` res+    where+    res = (startPos, endPos)+    realBsStart = utf8Position + bsStart+    realBsEnd = realBsStart + bsLen+    startPos = bsDropToTDrop Array.! realBsStart+    endPos = bsDropToTDrop Array.! realBsEnd
+ Duckling/Types/Stash.hs view
@@ -0,0 +1,66 @@+-- 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 RecordWildCards #-}+{-# LANGUAGE NoRebindableSyntax #-}++module Duckling.Types.Stash where++import qualified Data.IntMap.Strict as IntMap+import Data.IntMap.Strict (IntMap)+import qualified Data.HashSet as HashSet+import Data.HashSet (HashSet)+import Data.Maybe+import Prelude++import Duckling.Types++newtype Stash = Stash { getSet :: IntMap (HashSet Node) }++filter :: (Node -> Bool) -> Stash -> Stash+filter p Stash{..} = Stash (IntMap.map (HashSet.filter p) getSet)++toPosOrderedList:: Stash -> [Node]+toPosOrderedList Stash{..} = concatMap HashSet.toList $ IntMap.elems getSet++toPosOrderedListFrom :: Stash -> Int -> [Node]+toPosOrderedListFrom Stash{..} pos =+  concatMap HashSet.toList $ maybeToList equal ++ IntMap.elems bigger+  where+  (_smaller, equal, bigger) = IntMap.splitLookup pos getSet+  -- this is where we take advantage of the order++empty :: Stash+empty = Stash IntMap.empty++fromList :: [Node] -> Stash+fromList ns = Stash (IntMap.fromListWith HashSet.union $ map mkKV ns)+  where+  mkKV n@(Node { nodeRange = Range start _ }) = (start, HashSet.singleton n)++union :: Stash -> Stash -> Stash+union (Stash set1) (Stash set2) =+  Stash (IntMap.unionWith HashSet.union set1 set2)++-- Checks if two stashes have equal amount of Nodes on each position.+-- Used to detect a fixpoint, because the Stashes are only growing.+--+-- Not proud of this, but the algorithm shouldn't use it as the termination+-- condition, it should know when it stopped adding tokens+sizeEqual :: Stash -> Stash -> Bool+sizeEqual (Stash set1) (Stash set2) =+  go (IntMap.toAscList set1) (IntMap.toAscList set2)+  where+  go [] [] = True+  go [] (_:_) = False+  go (_:_) [] = False+  go ((k1, h1):rest1) ((k2, h2):rest2) =+    k1 == k2 && HashSet.size h1 == HashSet.size h2 && go rest1 rest2++null :: Stash -> Bool+null (Stash set) = IntMap.null set
+ Duckling/Url/Corpus.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Url.Corpus+  ( corpus+  , negativeCorpus+  ) where++import Data.String+import Prelude++import Duckling.Testing.Types+import Duckling.Url.Types++corpus :: Corpus+corpus = (testContext, allExamples)++negativeCorpus :: NegativeCorpus+negativeCorpus = (testContext, examples)+  where+    examples =+      [ "foo"+      , "MYHOST"+      , "hey:42"+      , "25"+      ]++allExamples :: [Example]+allExamples = concat+  [ examples (UrlData "http://www.bla.com" "bla.com")+             [ "http://www.bla.com"+             ]+  , examples (UrlData "www.bla.com:8080/path" "bla.com")+             [ "www.bla.com:8080/path"+             ]+  , examples (UrlData "https://myserver?foo=bar" "myserver")+             [ "https://myserver?foo=bar"+             ]+  , examples (UrlData "cnn.com/info" "cnn.com")+             [ "cnn.com/info"+             ]+  , examples (UrlData "bla.com/path/path?ext=%23&foo=bla" "bla.com")+             [ "bla.com/path/path?ext=%23&foo=bla"+             ]+  , examples (UrlData "localhost" "localhost")+             [ "localhost"+             ]+  , examples (UrlData "localhost:8000" "localhost")+             [ "localhost:8000"+             ]+  , examples (UrlData "http://kimchi" "kimchi")+             [ "http://kimchi"+             ]+  , examples (UrlData "https://500px.com:443/about" "500px.com")+             [ "https://500px.com:443/about"+             ]+  , examples (UrlData "www2.foo-bar.net?foo=bar" "foo-bar.net")+             [ "www2.foo-bar.net?foo=bar"+             ]+  , examples (UrlData "https://api.wit.ai/message?q=hi" "api.wit.ai")+             [ "https://api.wit.ai/message?q=hi"+             ]+  , examples (UrlData "aMaZon.co.uk/?page=home" "amazon.co.uk")+             [ "aMaZon.co.uk/?page=home"+             ]+  ]
+ Duckling/Url/Helpers.hs view
@@ -0,0 +1,31 @@+-- 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.Url.Helpers+  ( url+  ) where++import Data.String+import Data.Text (Text)+import qualified Data.Text as Text+import Prelude++import qualified Duckling.Url.Types as TUrl+import Duckling.Url.Types (UrlData(..))++-- -----------------------------------------------------------------+-- Patterns++-- -----------------------------------------------------------------+-- Production++url :: Text -> Text -> UrlData+url value domain = UrlData+  {TUrl.value = value, TUrl.domain = Text.toLower domain}
+ Duckling/Url/Rules.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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}++module Duckling.Url.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Regex.Types+import Duckling.Types+import Duckling.Url.Helpers++ruleURL :: Rule+ruleURL = Rule+  { name = "url"+  , pattern =+    [ regex "((([a-zA-Z]+)://)?(w{2,3}[0-9]*\\.)?(([\\w_-]+\\.)+[a-z]{2,4})(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m:_:_protocol:_:domain:_:_:_port:_path:_query:_)):+       _) -> Just . Token Url $ url m domain+      _ -> Nothing+  }++ruleLocalhost :: Rule+ruleLocalhost = Rule+  { name = "localhost"+  , pattern =+    [ regex "((([a-zA-Z]+)://)?localhost(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m:_:_protocol:_:_port:_path:_query:_)):_) ->+        Just . Token Url $ url m "localhost"+      _ -> Nothing+  }++ruleLocalURL :: Rule+ruleLocalURL = Rule+  { name = "local url"+  , pattern =+    [ regex "(([a-zA-Z]+)://([\\w_-]+)(:(\\d+))?(/[^?\\s#]*)?(\\?[^\\s#]+)?)"+    ]+  , prod = \tokens -> case tokens of+      (Token RegexMatch (GroupMatch (m:_protocol:domain:_:_port:_path:_query:_)):+       _) -> Just . Token Url $ url m domain+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleURL+  , ruleLocalhost+  , ruleLocalURL+  ]
+ Duckling/Url/Types.hs view
@@ -0,0 +1,43 @@+-- Copyright (c) 2016-present, Facebook, Inc.+-- All rights reserved.+--+-- This source code is licensed under the BSD-style license found in the+-- LICENSE file in the root directory of this source tree. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Duckling.Url.Types where++import Control.DeepSeq+import Data.Aeson+import Data.Hashable+import Data.Maybe+import Data.Monoid+import Data.Text (Text)+import GHC.Generics+import Prelude++import Duckling.Resolve (Resolve(..))++data UrlData = UrlData+  { value :: Text+  , domain :: Text+  }+  deriving (Eq, Generic, Hashable, Ord, Show, NFData)++instance Resolve UrlData where+  type ResolvedValue UrlData = UrlData+  resolve _ x = Just x++instance ToJSON UrlData where+  toJSON (UrlData value domain) = object+    [ "value"  .= value+    , "domain" .= domain+    ]
+ Duckling/Volume/EN/Corpus.hs view
@@ -0,0 +1,42 @@+-- 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.Volume.EN.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Testing.Types+import Duckling.Volume.Types++corpus :: Corpus+corpus = (testContext, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (VolumeValue Millilitre 250)+             [ "250 milliliters"+             , "250ml"+             , "250 ml"+             ]+  , examples (VolumeValue Litre 2)+             [ "2 liters" ]+  , examples (VolumeValue Gallon 3)+             [ "3 gallons"+             , "3 gal"+             ]+  , examples (VolumeValue Hectolitre 3)+             [ "3 hectoliters"+             ]+  , examples (VolumeValue Litre 0.5)+             [ "half liter"+             ]+  ]
+ Duckling/Volume/EN/Rules.hs view
@@ -0,0 +1,51 @@+-- 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 #-}++module Duckling.Volume.EN.Rules+  ( rules ) where++import Data.Text (Text)+import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Types+import Duckling.Volume.Helpers+import qualified Duckling.Volume.Types as TVolume++ruleHalfLiter :: Rule+ruleHalfLiter = Rule+  { name = "half liter"+  , pattern = [ regex "half lit(er|re)" ]+  , prod = \_ -> Just . Token Volume . withUnit TVolume.Litre $ volume 0.5+  }++volumes :: [(Text, String, TVolume.Unit)]+volumes = [ ("<latent vol> ml"    , "m(l|illilit(er|re)s?)", TVolume.Millilitre)+          , ("<vol> hectoliters"  , "hectolit(er|re)s?"    , TVolume.Hectolitre)+          , ("<vol> liters"       , "l(it(er|re)s?)?"      , TVolume.Litre)+          , ("<latent vol> gallon", "gal(l?ons?)?"         , TVolume.Gallon)+          ]++ruleVolumes :: [Rule]+ruleVolumes = map go volumes+  where+    go :: (Text, String, TVolume.Unit) -> Rule+    go (name, regexPattern, u) = Rule+      { name = name+      , pattern = [ dimension Volume, regex regexPattern ]+      , prod = \tokens -> case tokens of+          (Token Volume vd:_) -> Just . Token Volume $ withUnit u vd+          _ -> Nothing+      }++rules :: [Rule]+rules = ruleHalfLiter:ruleVolumes
+ Duckling/Volume/ES/Corpus.hs view
@@ -0,0 +1,44 @@+-- 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.Volume.ES.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Lang+import Duckling.Resolve+import Duckling.Volume.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = ES}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (VolumeValue Millilitre 250)+             [ "250 mililitros"+             , "250ml"+             , "250 ml"+             ]+  , examples (VolumeValue Litre 2)+             [ "2 litros"+             ]+  , examples (VolumeValue Gallon 3)+             [ "3 galón"+             ]+  , examples (VolumeValue Hectolitre 3)+             [ "3 hectolitros"+             ]+  , examples (VolumeValue Litre 0.5)+             [ "medio litro"+             ]+  ]
+ Duckling/Volume/ES/Rules.hs view
@@ -0,0 +1,91 @@+-- 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 #-}++module Duckling.Volume.ES.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Types+import Duckling.Volume.Helpers+import qualified Duckling.Volume.Types as TVolume++ruleLatentVolMl :: Rule+ruleLatentVolMl = Rule+  { name = "<latent vol> ml"+  , pattern =+    [ dimension Volume+    , regex "m(l|ililitros?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Millilitre vd+      _ -> Nothing+  }++ruleVolHectoliters :: Rule+ruleVolHectoliters = Rule+  { name = "<vol> hectoliters"+  , pattern =+    [ dimension Volume+    , regex "hectolitros?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Hectolitre vd+      _ -> Nothing+  }++ruleVolLiters :: Rule+ruleVolLiters = Rule+  { name = "<vol> liters"+  , pattern =+    [ dimension Volume+    , regex "l(itros?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Litre vd+      _ -> Nothing+  }++ruleHalfLiter :: Rule+ruleHalfLiter = Rule+  { name = "half liter"+  , pattern =+    [ regex "medio litros?"+    ]+  , prod = \_ -> Just . Token Volume . withUnit TVolume.Litre $ volume 0.5+  }++ruleLatentVolGallon :: Rule+ruleLatentVolGallon = Rule+  { name = "<latent vol> gallon"+  , pattern =+    [ dimension Volume+    , regex "gal(o|\x00f3)ne?s?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Gallon vd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleHalfLiter+  , ruleLatentVolGallon+  , ruleLatentVolMl+  , ruleVolHectoliters+  , ruleVolLiters+  ]
+ Duckling/Volume/FR/Corpus.hs view
@@ -0,0 +1,46 @@+-- 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.Volume.FR.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Lang+import Duckling.Resolve+import Duckling.Volume.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = FR}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (VolumeValue Millilitre 250)+             [ "250 millilitres"+             , "250ml"+             , "250 ml"+             ]+  , examples (VolumeValue Litre 2)+             [ "2 litres"+             ]+  , examples (VolumeValue Gallon 3)+             [ "3 gallons"+             , "3 gal"+             ]+  , examples (VolumeValue Hectolitre 3)+             [ "3 hectolitres"+             ]+  , examples (VolumeValue Litre 0.5)+             [ "demi-litre"+             , "demi litre"+             ]+  ]
+ Duckling/Volume/FR/Rules.hs view
@@ -0,0 +1,91 @@+-- 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 #-}++module Duckling.Volume.FR.Rules+  ( rules ) where++import Prelude+import Data.String++import Duckling.Dimensions.Types+import Duckling.Types+import Duckling.Volume.Helpers+import qualified Duckling.Volume.Types as TVolume++ruleLatentVolMl :: Rule+ruleLatentVolMl = Rule+  { name = "<latent vol> ml"+  , pattern =+    [ dimension Volume+    , regex "m(l|illilitres?)"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Millilitre vd+      _ -> Nothing+  }++ruleVolHectoliters :: Rule+ruleVolHectoliters = Rule+  { name = "<vol> hectoliters"+  , pattern =+    [ dimension Volume+    , regex "hectolitres?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Hectolitre vd+      _ -> Nothing+  }++ruleVolLiters :: Rule+ruleVolLiters = Rule+  { name = "<vol> liters"+  , pattern =+    [ dimension Volume+    , regex "l(itres?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Litre vd+      _ -> Nothing+  }++ruleHalfLiter :: Rule+ruleHalfLiter = Rule+  { name = "half liter"+  , pattern =+    [ regex "demi( |-)?litre"+    ]+  , prod = \_ -> Just . Token Volume . withUnit TVolume.Litre $ volume 0.5+  }++ruleLatentVolGallon :: Rule+ruleLatentVolGallon = Rule+  { name = "<latent vol> gallon"+  , pattern =+    [ dimension Volume+    , regex "gal(l?ons?)?"+    ]+  , prod = \tokens -> case tokens of+      (Token Volume vd:_) ->+        Just . Token Volume $ withUnit TVolume.Gallon vd+      _ -> Nothing+  }++rules :: [Rule]+rules =+  [ ruleHalfLiter+  , ruleLatentVolGallon+  , ruleLatentVolMl+  , ruleVolHectoliters+  , ruleVolLiters+  ]
+ Duckling/Volume/GA/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. An additional grant+-- of patent rights can be found in the PATENTS file in the same directory.+++{-# LANGUAGE OverloadedStrings #-}++module Duckling.Volume.GA.Corpus+  ( corpus ) where++import Data.String+import Prelude++import Duckling.Lang+import Duckling.Resolve+import Duckling.Volume.Types+import Duckling.Testing.Types++corpus :: Corpus+corpus = (testContext {lang = GA}, allExamples)++allExamples :: [Example]+allExamples = concat+  [ examples (VolumeValue Millilitre 250)+             [ "250 millilítir"+             , "250 millilitir"+             , "250ml"+             , "250 ml"+             ]+  , examples (VolumeValue Litre 2)+             [ "2 lítir"+             ]+  , examples (VolumeValue Gallon 5)+             [ "5 galúin"+             ]+  ]
+ 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/KO/Corpus.hs view

file too large to diff

+ Duckling/Volume/KO/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/Rules.hs view

file too large to diff

+ Duckling/Volume/Types.hs view

file too large to diff

+ LICENSE view

file too large to diff

+ PATENTS view

file too large to diff

+ README.md view

file too large to diff

+ Setup.hs view

file too large to diff

+ duckling.cabal 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/ExampleMain.hs view

file too large to diff

+ exe/RegenMain.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/HR/Tests.hs view

file too large to diff

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

file too large to diff

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

file too large to diff

+ tests/Duckling/AmountOfMoney/NB/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/SV/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/Api/Tests.hs view

file too large to diff

+ tests/Duckling/Dimensions/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/KO/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/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/EN/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/JA/Tests.hs view

file too large to diff

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

file too large to diff

+ tests/Duckling/Duration/NB/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/SV/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/Tests.hs view

file too large to diff

+ tests/Duckling/Duration/ZH/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/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/AR/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/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/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/HR/Tests.hs view

file too large to diff

+ tests/Duckling/Numeral/ID/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/KO/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/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/SV/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/DA/Tests.hs view

file too large to diff

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

file too large to diff

+ tests/Duckling/Ordinal/EN/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/HR/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/KO/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/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/PT/Tests.hs view

file too large to diff

+ tests/Duckling/PhoneNumber/Tests.hs view

file too large to diff

+ tests/Duckling/Quantity/EN/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/KO/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/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/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/KO/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/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/DA/Tests.hs view

file too large to diff

+ tests/Duckling/Time/DE/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/IT/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/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/SV/Tests.hs view

file too large to diff

+ tests/Duckling/Time/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/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/KO/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/Tests.hs view

file too large to diff

+ tests/TestMain.hs view

file too large to diff