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 +113/−0
- Duckling/AmountOfMoney/EN/Rules.hs +192/−0
- Duckling/AmountOfMoney/ES/Corpus.hs +67/−0
- Duckling/AmountOfMoney/ES/Rules.hs +123/−0
- Duckling/AmountOfMoney/FR/Corpus.hs +65/−0
- Duckling/AmountOfMoney/FR/Rules.hs +136/−0
- Duckling/AmountOfMoney/GA/Corpus.hs +86/−0
- Duckling/AmountOfMoney/GA/Rules.hs +159/−0
- Duckling/AmountOfMoney/HR/Corpus.hs +96/−0
- Duckling/AmountOfMoney/HR/Rules.hs +200/−0
- Duckling/AmountOfMoney/Helpers.hs +48/−0
- Duckling/AmountOfMoney/ID/Corpus.hs +82/−0
- Duckling/AmountOfMoney/ID/Rules.hs +84/−0
- Duckling/AmountOfMoney/KO/Corpus.hs +78/−0
- Duckling/AmountOfMoney/KO/Rules.hs +161/−0
- Duckling/AmountOfMoney/NB/Corpus.hs +86/−0
- Duckling/AmountOfMoney/NB/Rules.hs +163/−0
- Duckling/AmountOfMoney/PT/Corpus.hs +74/−0
- Duckling/AmountOfMoney/PT/Rules.hs +133/−0
- Duckling/AmountOfMoney/RO/Corpus.hs +120/−0
- Duckling/AmountOfMoney/RO/Rules.hs +210/−0
- Duckling/AmountOfMoney/Rules.hs +129/−0
- Duckling/AmountOfMoney/SV/Corpus.hs +91/−0
- Duckling/AmountOfMoney/SV/Rules.hs +169/−0
- Duckling/AmountOfMoney/Types.hs +109/−0
- Duckling/AmountOfMoney/VI/Corpus.hs +103/−0
- Duckling/AmountOfMoney/VI/Rules.hs +153/−0
- Duckling/Api.hs +62/−0
- Duckling/Core.hs +58/−0
- Duckling/Debug.hs +85/−0
- Duckling/Dimensions.hs +104/−0
- Duckling/Dimensions/AR.hs +19/−0
- Duckling/Dimensions/Common.hs +21/−0
- Duckling/Dimensions/DA.hs +21/−0
- Duckling/Dimensions/DE.hs +21/−0
- Duckling/Dimensions/EN.hs +25/−0
- Duckling/Dimensions/ES.hs +24/−0
- Duckling/Dimensions/ET.hs +19/−0
- Duckling/Dimensions/FR.hs +25/−0
- Duckling/Dimensions/GA.hs +24/−0
- Duckling/Dimensions/HE.hs +21/−0
- Duckling/Dimensions/HR.hs +25/−0
- Duckling/Dimensions/ID.hs +19/−0
- Duckling/Dimensions/IT.hs +23/−0
- Duckling/Dimensions/JA.hs +22/−0
- Duckling/Dimensions/KO.hs +25/−0
- Duckling/Dimensions/MY.hs +18/−0
- Duckling/Dimensions/NB.hs +21/−0
- Duckling/Dimensions/NL.hs +21/−0
- Duckling/Dimensions/PL.hs +21/−0
- Duckling/Dimensions/PT.hs +25/−0
- Duckling/Dimensions/RO.hs +25/−0
- Duckling/Dimensions/RU.hs +19/−0
- Duckling/Dimensions/SV.hs +21/−0
- Duckling/Dimensions/TR.hs +19/−0
- Duckling/Dimensions/Types.hs +181/−0
- Duckling/Dimensions/UK.hs +19/−0
- Duckling/Dimensions/VI.hs +21/−0
- Duckling/Dimensions/ZH.hs +22/−0
- Duckling/Distance/EN/Corpus.hs +43/−0
- Duckling/Distance/EN/Rules.hs +86/−0
- Duckling/Distance/ES/Corpus.hs +48/−0
- Duckling/Distance/ES/Rules.hs +81/−0
- Duckling/Distance/FR/Corpus.hs +48/−0
- Duckling/Distance/FR/Rules.hs +81/−0
- Duckling/Distance/GA/Corpus.hs +47/−0
- Duckling/Distance/GA/Rules.hs +123/−0
- Duckling/Distance/HR/Corpus.hs +45/−0
- Duckling/Distance/HR/Rules.hs +92/−0
- Duckling/Distance/Helpers.hs +41/−0
- Duckling/Distance/KO/Corpus.hs +56/−0
- Duckling/Distance/KO/Rules.hs +154/−0
- Duckling/Distance/NL/Corpus.hs +50/−0
- Duckling/Distance/NL/Rules.hs +81/−0
- Duckling/Distance/PT/Corpus.hs +48/−0
- Duckling/Distance/PT/Rules.hs +81/−0
- Duckling/Distance/RO/Corpus.hs +47/−0
- Duckling/Distance/RO/Rules.hs +123/−0
- Duckling/Distance/Rules.hs +41/−0
- Duckling/Distance/Types.hs +65/−0
- Duckling/Duration/DA/Rules.hs +142/−0
- Duckling/Duration/DE/Rules.hs +140/−0
- Duckling/Duration/EN/Corpus.hs +65/−0
- Duckling/Duration/EN/Rules.hs +153/−0
- Duckling/Duration/FR/Corpus.hs +66/−0
- Duckling/Duration/FR/Rules.hs +104/−0
- Duckling/Duration/GA/Corpus.hs +42/−0
- Duckling/Duration/GA/Rules.hs +78/−0
- Duckling/Duration/HE/Rules.hs +124/−0
- Duckling/Duration/HR/Rules.hs +141/−0
- Duckling/Duration/Helpers.hs +50/−0
- Duckling/Duration/IT/Rules.hs +68/−0
- Duckling/Duration/JA/Corpus.hs +40/−0
- Duckling/Duration/KO/Corpus.hs +40/−0
- Duckling/Duration/KO/Rules.hs +112/−0
- Duckling/Duration/NB/Corpus.hs +47/−0
- Duckling/Duration/NB/Rules.hs +129/−0
- Duckling/Duration/PL/Corpus.hs +49/−0
- Duckling/Duration/PL/Rules.hs +131/−0
- Duckling/Duration/PT/Corpus.hs +41/−0
- Duckling/Duration/RO/Corpus.hs +52/−0
- Duckling/Duration/RO/Rules.hs +81/−0
- Duckling/Duration/Rules.hs +42/−0
- Duckling/Duration/SV/Corpus.hs +48/−0
- Duckling/Duration/SV/Rules.hs +131/−0
- Duckling/Duration/Types.hs +48/−0
- Duckling/Duration/ZH/Corpus.hs +39/−0
- Duckling/Email/Corpus.hs +47/−0
- Duckling/Email/EN/Corpus.hs +38/−0
- Duckling/Email/EN/Rules.hs +40/−0
- Duckling/Email/FR/Corpus.hs +40/−0
- Duckling/Email/FR/Rules.hs +40/−0
- Duckling/Email/IT/Corpus.hs +40/−0
- Duckling/Email/IT/Rules.hs +40/−0
- Duckling/Email/Rules.hs +39/−0
- Duckling/Email/Types.hs +35/−0
- Duckling/Engine.hs +228/−0
- Duckling/Engine/Regex.hs +14/−0
- Duckling/Lang.hs +54/−0
- Duckling/Numeral/AR/Corpus.hs +117/−0
- Duckling/Numeral/AR/Rules.hs +371/−0
- Duckling/Numeral/DA/Corpus.hs +101/−0
- Duckling/Numeral/DA/Rules.hs +327/−0
- Duckling/Numeral/DE/Corpus.hs +133/−0
- Duckling/Numeral/DE/Rules.hs +389/−0
- Duckling/Numeral/EN/Corpus.hs +157/−0
- Duckling/Numeral/EN/Rules.hs +303/−0
- Duckling/Numeral/ES/Corpus.hs +110/−0
- Duckling/Numeral/ES/Rules.hs +315/−0
- Duckling/Numeral/ET/Corpus.hs +109/−0
- Duckling/Numeral/ET/Rules.hs +306/−0
- Duckling/Numeral/FR/Corpus.hs +127/−0
- Duckling/Numeral/FR/Rules.hs +330/−0
- Duckling/Numeral/GA/Corpus.hs +41/−0
- Duckling/Numeral/GA/Rules.hs +256/−0
- Duckling/Numeral/HE/Corpus.hs +94/−0
- Duckling/Numeral/HE/Rules.hs +389/−0
- Duckling/Numeral/HR/Corpus.hs +127/−0
- Duckling/Numeral/HR/Rules.hs +383/−0
- Duckling/Numeral/Helpers.hs +128/−0
- Duckling/Numeral/ID/Corpus.hs +118/−0
- Duckling/Numeral/ID/Rules.hs +274/−0
- Duckling/Numeral/IT/Corpus.hs +155/−0
- Duckling/Numeral/IT/Rules.hs +324/−0
- Duckling/Numeral/JA/Corpus.hs +109/−0
- Duckling/Numeral/JA/Rules.hs +373/−0
- Duckling/Numeral/KO/Corpus.hs +194/−0
- Duckling/Numeral/KO/Rules.hs +334/−0
- Duckling/Numeral/MY/Corpus.hs +71/−0
- Duckling/Numeral/MY/Rules.hs +181/−0
- Duckling/Numeral/NB/Corpus.hs +126/−0
- Duckling/Numeral/NB/Rules.hs +325/−0
- Duckling/Numeral/NL/Corpus.hs +91/−0
- Duckling/Numeral/NL/Rules.hs +289/−0
- Duckling/Numeral/PL/Corpus.hs +125/−0
- Duckling/Numeral/PL/Rules.hs +613/−0
- Duckling/Numeral/PT/Corpus.hs +166/−0
- Duckling/Numeral/PT/Rules.hs +306/−0
- Duckling/Numeral/RO/Corpus.hs +192/−0
- Duckling/Numeral/RO/Rules.hs +316/−0
- Duckling/Numeral/RU/Corpus.hs +114/−0
- Duckling/Numeral/RU/Rules.hs +279/−0
- Duckling/Numeral/SV/Corpus.hs +106/−0
- Duckling/Numeral/SV/Rules.hs +323/−0
- Duckling/Numeral/TR/Corpus.hs +180/−0
- Duckling/Numeral/TR/Rules.hs +733/−0
- Duckling/Numeral/Types.hs +62/−0
- Duckling/Numeral/UK/Corpus.hs +114/−0
- Duckling/Numeral/UK/Rules.hs +278/−0
- Duckling/Numeral/VI/Corpus.hs +111/−0
- Duckling/Numeral/VI/Rules.hs +335/−0
- Duckling/Numeral/ZH/Corpus.hs +109/−0
- Duckling/Numeral/ZH/Rules.hs +201/−0
- Duckling/Ordinal/AR/Corpus.hs +29/−0
- Duckling/Ordinal/AR/Rules.hs +123/−0
- Duckling/Ordinal/DA/Corpus.hs +31/−0
- Duckling/Ordinal/DA/Rules.hs +85/−0
- Duckling/Ordinal/DE/Corpus.hs +31/−0
- Duckling/Ordinal/DE/Rules.hs +93/−0
- Duckling/Ordinal/EN/Corpus.hs +65/−0
- Duckling/Ordinal/EN/Rules.hs +109/−0
- Duckling/Ordinal/ES/Rules.hs +94/−0
- Duckling/Ordinal/ET/Corpus.hs +31/−0
- Duckling/Ordinal/ET/Rules.hs +71/−0
- Duckling/Ordinal/FR/Corpus.hs +49/−0
- Duckling/Ordinal/FR/Rules.hs +96/−0
- Duckling/Ordinal/GA/Corpus.hs +46/−0
- Duckling/Ordinal/GA/Rules.hs +121/−0
- Duckling/Ordinal/HE/Corpus.hs +29/−0
- Duckling/Ordinal/HE/Rules.hs +270/−0
- Duckling/Ordinal/HR/Corpus.hs +50/−0
- Duckling/Ordinal/HR/Rules.hs +178/−0
- Duckling/Ordinal/Helpers.hs +27/−0
- Duckling/Ordinal/ID/Corpus.hs +38/−0
- Duckling/Ordinal/ID/Rules.hs +62/−0
- Duckling/Ordinal/IT/Corpus.hs +87/−0
- Duckling/Ordinal/IT/Rules.hs +92/−0
- Duckling/Ordinal/JA/Corpus.hs +29/−0
- Duckling/Ordinal/JA/Rules.hs +40/−0
- Duckling/Ordinal/KO/Corpus.hs +38/−0
- Duckling/Ordinal/KO/Rules.hs +40/−0
- Duckling/Ordinal/NB/Corpus.hs +40/−0
- Duckling/Ordinal/NB/Rules.hs +93/−0
- Duckling/Ordinal/NL/Corpus.hs +39/−0
- Duckling/Ordinal/NL/Rules.hs +79/−0
- Duckling/Ordinal/PL/Corpus.hs +30/−0
- Duckling/Ordinal/PL/Rules.hs +318/−0
- Duckling/Ordinal/PT/Corpus.hs +40/−0
- Duckling/Ordinal/PT/Rules.hs +87/−0
- Duckling/Ordinal/RO/Corpus.hs +68/−0
- Duckling/Ordinal/RO/Rules.hs +93/−0
- Duckling/Ordinal/RU/Corpus.hs +74/−0
- Duckling/Ordinal/RU/Rules.hs +110/−0
- Duckling/Ordinal/SV/Corpus.hs +43/−0
- Duckling/Ordinal/SV/Rules.hs +94/−0
- Duckling/Ordinal/TR/Corpus.hs +39/−0
- Duckling/Ordinal/TR/Rules.hs +95/−0
- Duckling/Ordinal/Types.hs +40/−0
- Duckling/Ordinal/UK/Corpus.hs +74/−0
- Duckling/Ordinal/UK/Rules.hs +110/−0
- Duckling/Ordinal/VI/Corpus.hs +31/−0
- Duckling/Ordinal/VI/Rules.hs +33/−0
- Duckling/Ordinal/ZH/Corpus.hs +36/−0
- Duckling/Ordinal/ZH/Rules.hs +40/−0
- Duckling/PhoneNumber/Corpus.hs +76/−0
- Duckling/PhoneNumber/PT/Corpus.hs +31/−0
- Duckling/PhoneNumber/PT/Rules.hs +56/−0
- Duckling/PhoneNumber/Rules.hs +54/−0
- Duckling/PhoneNumber/Types.hs +54/−0
- Duckling/Quantity/EN/Corpus.hs +34/−0
- Duckling/Quantity/EN/Rules.hs +77/−0
- Duckling/Quantity/FR/Corpus.hs +36/−0
- Duckling/Quantity/FR/Rules.hs +62/−0
- Duckling/Quantity/HR/Corpus.hs +33/−0
- Duckling/Quantity/HR/Rules.hs +62/−0
- Duckling/Quantity/Helpers.hs +31/−0
- Duckling/Quantity/KO/Corpus.hs +39/−0
- Duckling/Quantity/KO/Rules.hs +84/−0
- Duckling/Quantity/PT/Corpus.hs +36/−0
- Duckling/Quantity/PT/Rules.hs +62/−0
- Duckling/Quantity/RO/Corpus.hs +36/−0
- Duckling/Quantity/RO/Rules.hs +57/−0
- Duckling/Quantity/Types.hs +61/−0
- Duckling/Ranking/Classifiers.hs +68/−0
- Duckling/Ranking/Classifiers/AR.hs +22/−0
- Duckling/Ranking/Classifiers/DA.hs +1566/−0
- Duckling/Ranking/Classifiers/DE.hs +1824/−0
- Duckling/Ranking/Classifiers/EN.hs +2133/−0
- Duckling/Ranking/Classifiers/ES.hs +1160/−0
- Duckling/Ranking/Classifiers/ET.hs +22/−0
- Duckling/Ranking/Classifiers/FR.hs +2395/−0
- Duckling/Ranking/Classifiers/GA.hs +155/−0
- Duckling/Ranking/Classifiers/HE.hs +992/−0
- Duckling/Ranking/Classifiers/HR.hs +1850/−0
- Duckling/Ranking/Classifiers/ID.hs +22/−0
- Duckling/Ranking/Classifiers/IT.hs +2085/−0
- Duckling/Ranking/Classifiers/JA.hs +22/−0
- Duckling/Ranking/Classifiers/KO.hs +1458/−0
- Duckling/Ranking/Classifiers/MY.hs +22/−0
- Duckling/Ranking/Classifiers/NB.hs +1603/−0
- Duckling/Ranking/Classifiers/NL.hs +22/−0
- Duckling/Ranking/Classifiers/PL.hs +2307/−0
- Duckling/Ranking/Classifiers/PT.hs +1279/−0
- Duckling/Ranking/Classifiers/RO.hs +265/−0
- Duckling/Ranking/Classifiers/RU.hs +22/−0
- Duckling/Ranking/Classifiers/SV.hs +1596/−0
- Duckling/Ranking/Classifiers/TR.hs +22/−0
- Duckling/Ranking/Classifiers/UK.hs +22/−0
- Duckling/Ranking/Classifiers/VI.hs +906/−0
- Duckling/Ranking/Classifiers/ZH.hs +753/−0
- Duckling/Ranking/Extraction.hs +45/−0
- Duckling/Ranking/Rank.hs +68/−0
- Duckling/Ranking/Types.hs +58/−0
- Duckling/Regex/Types.hs +30/−0
- Duckling/Resolve.hs +60/−0
- Duckling/Rules.hs +95/−0
- Duckling/Rules/AR.hs +35/−0
- Duckling/Rules/Common.hs +41/−0
- Duckling/Rules/DA.hs +38/−0
- Duckling/Rules/DE.hs +38/−0
- Duckling/Rules/EN.hs +44/−0
- Duckling/Rules/ES.hs +41/−0
- Duckling/Rules/ET.hs +35/−0
- Duckling/Rules/FR.hs +44/−0
- Duckling/Rules/GA.hs +42/−0
- Duckling/Rules/HE.hs +38/−0
- Duckling/Rules/HR.hs +43/−0
- Duckling/Rules/ID.hs +36/−0
- Duckling/Rules/IT.hs +41/−0
- Duckling/Rules/JA.hs +37/−0
- Duckling/Rules/KO.hs +43/−0
- Duckling/Rules/MY.hs +34/−0
- Duckling/Rules/NB.hs +39/−0
- Duckling/Rules/NL.hs +37/−0
- Duckling/Rules/PL.hs +38/−0
- Duckling/Rules/PT.hs +43/−0
- Duckling/Rules/RO.hs +43/−0
- Duckling/Rules/RU.hs +35/−0
- Duckling/Rules/SV.hs +39/−0
- Duckling/Rules/TR.hs +35/−0
- Duckling/Rules/UK.hs +35/−0
- Duckling/Rules/VI.hs +38/−0
- Duckling/Rules/ZH.hs +38/−0
- Duckling/Temperature/EN/Corpus.hs +50/−0
- Duckling/Temperature/EN/Rules.hs +86/−0
- Duckling/Temperature/ES/Corpus.hs +51/−0
- Duckling/Temperature/ES/Rules.hs +85/−0
- Duckling/Temperature/FR/Corpus.hs +53/−0
- Duckling/Temperature/FR/Rules.hs +85/−0
- Duckling/Temperature/GA/Corpus.hs +49/−0
- Duckling/Temperature/GA/Rules.hs +85/−0
- Duckling/Temperature/HR/Corpus.hs +45/−0
- Duckling/Temperature/HR/Rules.hs +67/−0
- Duckling/Temperature/Helpers.hs +37/−0
- Duckling/Temperature/IT/Corpus.hs +52/−0
- Duckling/Temperature/IT/Rules.hs +67/−0
- Duckling/Temperature/JA/Corpus.hs +41/−0
- Duckling/Temperature/JA/Rules.hs +97/−0
- Duckling/Temperature/KO/Corpus.hs +41/−0
- Duckling/Temperature/KO/Rules.hs +95/−0
- Duckling/Temperature/PT/Corpus.hs +51/−0
- Duckling/Temperature/PT/Rules.hs +85/−0
- Duckling/Temperature/RO/Corpus.hs +45/−0
- Duckling/Temperature/RO/Rules.hs +67/−0
- Duckling/Temperature/Rules.hs +43/−0
- Duckling/Temperature/Types.hs +56/−0
- Duckling/Temperature/ZH/Corpus.hs +53/−0
- Duckling/Temperature/ZH/Rules.hs +97/−0
- Duckling/Testing/Types.hs +72/−0
- Duckling/Time/Corpus.hs +57/−0
- Duckling/Time/DA/Corpus.hs +633/−0
- Duckling/Time/DA/Rules.hs +2007/−0
- Duckling/Time/DE/Corpus.hs +618/−0
- Duckling/Time/DE/Rules.hs +2024/−0
- Duckling/Time/EN/Corpus.hs +783/−0
- Duckling/Time/EN/Rules.hs +1597/−0
- Duckling/Time/ES/Corpus.hs +416/−0
- Duckling/Time/ES/Rules.hs +1593/−0
- Duckling/Time/FR/Corpus.hs +774/−0
- Duckling/Time/FR/Rules.hs +2179/−0
- Duckling/Time/GA/Corpus.hs +59/−0
- Duckling/Time/GA/Rules.hs +872/−0
- Duckling/Time/HE/Corpus.hs +292/−0
- Duckling/Time/HE/Rules.hs +1556/−0
- Duckling/Time/HR/Corpus.hs +671/−0
- Duckling/Time/HR/Rules.hs +1898/−0
- Duckling/Time/Helpers.hs +508/−0
- Duckling/Time/IT/Corpus.hs +814/−0
- Duckling/Time/IT/Rules.hs +2569/−0
- Duckling/Time/KO/Corpus.hs +548/−0
- Duckling/Time/KO/Rules.hs +1358/−0
- Duckling/Time/NB/Corpus.hs +644/−0
- Duckling/Time/NB/Rules.hs +1965/−0
- Duckling/Time/PL/Corpus.hs +761/−0
- Duckling/Time/PL/Rules.hs +1959/−0
- Duckling/Time/PT/Corpus.hs +475/−0
- Duckling/Time/PT/Rules.hs +1655/−0
- Duckling/Time/RO/Corpus.hs +91/−0
- Duckling/Time/RO/Rules.hs +1503/−0
- Duckling/Time/SV/Corpus.hs +615/−0
- Duckling/Time/SV/Rules.hs +1923/−0
- Duckling/Time/TimeZone/Parse.hs +194/−0
- Duckling/Time/Types.hs +698/−0
- Duckling/Time/VI/Corpus.hs +370/−0
- Duckling/Time/VI/Rules.hs +1211/−0
- Duckling/Time/ZH/Corpus.hs +418/−0
- Duckling/Time/ZH/Rules.hs +1213/−0
- Duckling/TimeGrain/DA/Rules.hs +41/−0
- Duckling/TimeGrain/DE/Rules.hs +41/−0
- Duckling/TimeGrain/EN/Rules.hs +40/−0
- Duckling/TimeGrain/ES/Rules.hs +41/−0
- Duckling/TimeGrain/FR/Rules.hs +40/−0
- Duckling/TimeGrain/GA/Rules.hs +41/−0
- Duckling/TimeGrain/HE/Rules.hs +40/−0
- Duckling/TimeGrain/HR/Rules.hs +40/−0
- Duckling/TimeGrain/IT/Rules.hs +41/−0
- Duckling/TimeGrain/JA/Rules.hs +40/−0
- Duckling/TimeGrain/KO/Rules.hs +41/−0
- Duckling/TimeGrain/NB/Rules.hs +41/−0
- Duckling/TimeGrain/PL/Rules.hs +41/−0
- Duckling/TimeGrain/PT/Rules.hs +40/−0
- Duckling/TimeGrain/RO/Rules.hs +41/−0
- Duckling/TimeGrain/SV/Rules.hs +41/−0
- Duckling/TimeGrain/Types.hs +69/−0
- Duckling/TimeGrain/VI/Rules.hs +40/−0
- Duckling/TimeGrain/ZH/Rules.hs +40/−0
- Duckling/Types.hs +153/−0
- Duckling/Types/Document.hs +199/−0
- Duckling/Types/Stash.hs +66/−0
- Duckling/Url/Corpus.hs +73/−0
- Duckling/Url/Helpers.hs +31/−0
- Duckling/Url/Rules.hs +64/−0
- Duckling/Url/Types.hs +43/−0
- Duckling/Volume/EN/Corpus.hs +42/−0
- Duckling/Volume/EN/Rules.hs +51/−0
- Duckling/Volume/ES/Corpus.hs +44/−0
- Duckling/Volume/ES/Rules.hs +91/−0
- Duckling/Volume/FR/Corpus.hs +46/−0
- Duckling/Volume/FR/Rules.hs +91/−0
- Duckling/Volume/GA/Corpus.hs +39/−0
- Duckling/Volume/GA/Rules.hs too large to diff
- Duckling/Volume/HR/Corpus.hs too large to diff
- Duckling/Volume/HR/Rules.hs too large to diff
- Duckling/Volume/Helpers.hs too large to diff
- Duckling/Volume/IT/Corpus.hs too large to diff
- Duckling/Volume/IT/Rules.hs too large to diff
- Duckling/Volume/KO/Corpus.hs too large to diff
- Duckling/Volume/KO/Rules.hs too large to diff
- Duckling/Volume/NL/Corpus.hs too large to diff
- Duckling/Volume/NL/Rules.hs too large to diff
- Duckling/Volume/PT/Corpus.hs too large to diff
- Duckling/Volume/PT/Rules.hs too large to diff
- Duckling/Volume/RO/Corpus.hs too large to diff
- Duckling/Volume/RO/Rules.hs too large to diff
- Duckling/Volume/Rules.hs too large to diff
- Duckling/Volume/Types.hs too large to diff
- LICENSE too large to diff
- PATENTS too large to diff
- README.md too large to diff
- Setup.hs too large to diff
- duckling.cabal too large to diff
- exe/Duckling/Data/TimeZone.hs too large to diff
- exe/Duckling/Ranking/Generate.hs too large to diff
- exe/Duckling/Ranking/Train.hs too large to diff
- exe/ExampleMain.hs too large to diff
- exe/RegenMain.hs too large to diff
- tests/Duckling/AmountOfMoney/EN/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/ES/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/FR/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/GA/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/HR/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/ID/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/KO/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/NB/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/PT/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/RO/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/SV/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/Tests.hs too large to diff
- tests/Duckling/AmountOfMoney/VI/Tests.hs too large to diff
- tests/Duckling/Api/Tests.hs too large to diff
- tests/Duckling/Dimensions/Tests.hs too large to diff
- tests/Duckling/Distance/EN/Tests.hs too large to diff
- tests/Duckling/Distance/ES/Tests.hs too large to diff
- tests/Duckling/Distance/FR/Tests.hs too large to diff
- tests/Duckling/Distance/GA/Tests.hs too large to diff
- tests/Duckling/Distance/HR/Tests.hs too large to diff
- tests/Duckling/Distance/KO/Tests.hs too large to diff
- tests/Duckling/Distance/NL/Tests.hs too large to diff
- tests/Duckling/Distance/PT/Tests.hs too large to diff
- tests/Duckling/Distance/RO/Tests.hs too large to diff
- tests/Duckling/Distance/Tests.hs too large to diff
- tests/Duckling/Duration/EN/Tests.hs too large to diff
- tests/Duckling/Duration/FR/Tests.hs too large to diff
- tests/Duckling/Duration/GA/Tests.hs too large to diff
- tests/Duckling/Duration/JA/Tests.hs too large to diff
- tests/Duckling/Duration/KO/Tests.hs too large to diff
- tests/Duckling/Duration/NB/Tests.hs too large to diff
- tests/Duckling/Duration/PL/Tests.hs too large to diff
- tests/Duckling/Duration/PT/Tests.hs too large to diff
- tests/Duckling/Duration/RO/Tests.hs too large to diff
- tests/Duckling/Duration/SV/Tests.hs too large to diff
- tests/Duckling/Duration/Tests.hs too large to diff
- tests/Duckling/Duration/ZH/Tests.hs too large to diff
- tests/Duckling/Email/EN/Tests.hs too large to diff
- tests/Duckling/Email/FR/Tests.hs too large to diff
- tests/Duckling/Email/IT/Tests.hs too large to diff
- tests/Duckling/Email/Tests.hs too large to diff
- tests/Duckling/Engine/Tests.hs too large to diff
- tests/Duckling/Numeral/AR/Tests.hs too large to diff
- tests/Duckling/Numeral/DA/Tests.hs too large to diff
- tests/Duckling/Numeral/DE/Tests.hs too large to diff
- tests/Duckling/Numeral/EN/Tests.hs too large to diff
- tests/Duckling/Numeral/ES/Tests.hs too large to diff
- tests/Duckling/Numeral/ET/Tests.hs too large to diff
- tests/Duckling/Numeral/FR/Tests.hs too large to diff
- tests/Duckling/Numeral/GA/Tests.hs too large to diff
- tests/Duckling/Numeral/HE/Tests.hs too large to diff
- tests/Duckling/Numeral/HR/Tests.hs too large to diff
- tests/Duckling/Numeral/ID/Tests.hs too large to diff
- tests/Duckling/Numeral/IT/Tests.hs too large to diff
- tests/Duckling/Numeral/JA/Tests.hs too large to diff
- tests/Duckling/Numeral/KO/Tests.hs too large to diff
- tests/Duckling/Numeral/MY/Tests.hs too large to diff
- tests/Duckling/Numeral/NB/Tests.hs too large to diff
- tests/Duckling/Numeral/NL/Tests.hs too large to diff
- tests/Duckling/Numeral/PL/Tests.hs too large to diff
- tests/Duckling/Numeral/PT/Tests.hs too large to diff
- tests/Duckling/Numeral/RO/Tests.hs too large to diff
- tests/Duckling/Numeral/RU/Tests.hs too large to diff
- tests/Duckling/Numeral/SV/Tests.hs too large to diff
- tests/Duckling/Numeral/TR/Tests.hs too large to diff
- tests/Duckling/Numeral/Tests.hs too large to diff
- tests/Duckling/Numeral/UK/Tests.hs too large to diff
- tests/Duckling/Numeral/VI/Tests.hs too large to diff
- tests/Duckling/Numeral/ZH/Tests.hs too large to diff
- tests/Duckling/Ordinal/AR/Tests.hs too large to diff
- tests/Duckling/Ordinal/DA/Tests.hs too large to diff
- tests/Duckling/Ordinal/DE/Tests.hs too large to diff
- tests/Duckling/Ordinal/EN/Tests.hs too large to diff
- tests/Duckling/Ordinal/ET/Tests.hs too large to diff
- tests/Duckling/Ordinal/FR/Tests.hs too large to diff
- tests/Duckling/Ordinal/GA/Tests.hs too large to diff
- tests/Duckling/Ordinal/HE/Tests.hs too large to diff
- tests/Duckling/Ordinal/HR/Tests.hs too large to diff
- tests/Duckling/Ordinal/ID/Tests.hs too large to diff
- tests/Duckling/Ordinal/IT/Tests.hs too large to diff
- tests/Duckling/Ordinal/JA/Tests.hs too large to diff
- tests/Duckling/Ordinal/KO/Tests.hs too large to diff
- tests/Duckling/Ordinal/NB/Tests.hs too large to diff
- tests/Duckling/Ordinal/NL/Tests.hs too large to diff
- tests/Duckling/Ordinal/PL/Tests.hs too large to diff
- tests/Duckling/Ordinal/PT/Tests.hs too large to diff
- tests/Duckling/Ordinal/RO/Tests.hs too large to diff
- tests/Duckling/Ordinal/RU/Tests.hs too large to diff
- tests/Duckling/Ordinal/SV/Tests.hs too large to diff
- tests/Duckling/Ordinal/TR/Tests.hs too large to diff
- tests/Duckling/Ordinal/Tests.hs too large to diff
- tests/Duckling/Ordinal/UK/Tests.hs too large to diff
- tests/Duckling/Ordinal/VI/Tests.hs too large to diff
- tests/Duckling/Ordinal/ZH/Tests.hs too large to diff
- tests/Duckling/PhoneNumber/PT/Tests.hs too large to diff
- tests/Duckling/PhoneNumber/Tests.hs too large to diff
- tests/Duckling/Quantity/EN/Tests.hs too large to diff
- tests/Duckling/Quantity/FR/Tests.hs too large to diff
- tests/Duckling/Quantity/HR/Tests.hs too large to diff
- tests/Duckling/Quantity/KO/Tests.hs too large to diff
- tests/Duckling/Quantity/PT/Tests.hs too large to diff
- tests/Duckling/Quantity/RO/Tests.hs too large to diff
- tests/Duckling/Quantity/Tests.hs too large to diff
- tests/Duckling/Temperature/EN/Tests.hs too large to diff
- tests/Duckling/Temperature/ES/Tests.hs too large to diff
- tests/Duckling/Temperature/FR/Tests.hs too large to diff
- tests/Duckling/Temperature/GA/Tests.hs too large to diff
- tests/Duckling/Temperature/HR/Tests.hs too large to diff
- tests/Duckling/Temperature/IT/Tests.hs too large to diff
- tests/Duckling/Temperature/JA/Tests.hs too large to diff
- tests/Duckling/Temperature/KO/Tests.hs too large to diff
- tests/Duckling/Temperature/PT/Tests.hs too large to diff
- tests/Duckling/Temperature/RO/Tests.hs too large to diff
- tests/Duckling/Temperature/Tests.hs too large to diff
- tests/Duckling/Temperature/ZH/Tests.hs too large to diff
- tests/Duckling/Testing/Asserts.hs too large to diff
- tests/Duckling/Tests.hs too large to diff
- tests/Duckling/Time/DA/Tests.hs too large to diff
- tests/Duckling/Time/DE/Tests.hs too large to diff
- tests/Duckling/Time/EN/Tests.hs too large to diff
- tests/Duckling/Time/ES/Tests.hs too large to diff
- tests/Duckling/Time/FR/Tests.hs too large to diff
- tests/Duckling/Time/GA/Tests.hs too large to diff
- tests/Duckling/Time/HE/Tests.hs too large to diff
- tests/Duckling/Time/HR/Tests.hs too large to diff
- tests/Duckling/Time/IT/Tests.hs too large to diff
- tests/Duckling/Time/KO/Tests.hs too large to diff
- tests/Duckling/Time/NB/Tests.hs too large to diff
- tests/Duckling/Time/PL/Tests.hs too large to diff
- tests/Duckling/Time/PT/Tests.hs too large to diff
- tests/Duckling/Time/RO/Tests.hs too large to diff
- tests/Duckling/Time/SV/Tests.hs too large to diff
- tests/Duckling/Time/Tests.hs too large to diff
- tests/Duckling/Time/VI/Tests.hs too large to diff
- tests/Duckling/Time/ZH/Tests.hs too large to diff
- tests/Duckling/Url/Tests.hs too large to diff
- tests/Duckling/Volume/EN/Tests.hs too large to diff
- tests/Duckling/Volume/ES/Tests.hs too large to diff
- tests/Duckling/Volume/FR/Tests.hs too large to diff
- tests/Duckling/Volume/GA/Tests.hs too large to diff
- tests/Duckling/Volume/HR/Tests.hs too large to diff
- tests/Duckling/Volume/IT/Tests.hs too large to diff
- tests/Duckling/Volume/KO/Tests.hs too large to diff
- tests/Duckling/Volume/NL/Tests.hs too large to diff
- tests/Duckling/Volume/PT/Tests.hs too large to diff
- tests/Duckling/Volume/RO/Tests.hs too large to diff
- tests/Duckling/Volume/Tests.hs too large to diff
- tests/TestMain.hs too large to diff
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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}
@@ -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 ¥."+ ]+ ]
@@ -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+ ]
@@ -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₩"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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}
@@ -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 센치미터"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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}
@@ -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+ ]
@@ -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)+ [ "百 日"+ , "百 日間"+ ]+ ]
@@ -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 시간"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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ą"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]+ ]
@@ -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 月"+ , "十 月"+ ]+ ]
@@ -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"+ ]+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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 ]
@@ -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+ }
@@ -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)
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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万"+ ]+ ]
@@ -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+ ]
@@ -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"+ , "사분의삼"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "ရှစ်သောင်း"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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Г"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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Г"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "الثاني"+ ]
@@ -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+ ]
@@ -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"+ ]
@@ -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+ ]
@@ -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"+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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ú"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "ארבעה"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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}
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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ª"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "第七"+ ]
@@ -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+ ]
@@ -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)+ [ "네째번"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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-й"+ , "девяносто девятый"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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ü"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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-й"+ , "дев‘яносто дев‘ятий"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "第九十一"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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 ]
@@ -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 ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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}
@@ -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 "콜라"))+ [ "콜라 세컵"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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
@@ -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 []
@@ -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}})]
@@ -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}})]
@@ -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}})]
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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}})]
@@ -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}})]
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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}})]
@@ -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}})]
@@ -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 []
@@ -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}})]
@@ -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 []
@@ -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 []
@@ -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}})]
@@ -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}})]
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) = []
@@ -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
@@ -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) = []
@@ -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) = []
@@ -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
@@ -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
@@ -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) = []
@@ -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
@@ -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
@@ -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) = []
@@ -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
@@ -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) = []
@@ -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
@@ -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) = []
@@ -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
@@ -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) = []
@@ -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) = []
@@ -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
@@ -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) = []
@@ -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
@@ -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
@@ -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) = []
@@ -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) = []
@@ -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) = []
@@ -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) = []
@@ -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) = []
@@ -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) = []
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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."+ ]+ ]
@@ -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+ ]
@@ -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}
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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度"+ ]+ ]
@@ -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+ ]
@@ -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도"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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+ ]
@@ -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度"+ ]+ ]
@@ -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+ ]
@@ -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)}
@@ -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)
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "שני בבוקר"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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월에"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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" )+ ]
@@ -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
@@ -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ư"+ ]+ ]
@@ -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+ ]
@@ -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)+ [ "儿童节下午三点十五"+ , "兒童節下午三點十五"+ ]+ ]
@@ -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+ ]
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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+ }
@@ -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
@@ -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+ }
@@ -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+ }
@@ -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
@@ -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
@@ -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
@@ -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"+ ]+ ]
@@ -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}
@@ -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+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
@@ -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+ ]
@@ -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"+ ]+ ]
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff