module Duckling.Time.HU.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.Regex.Types
import Duckling.Types
import Duckling.Time.Helpers
import qualified Duckling.Time.Types as TTime
import qualified Duckling.TimeGrain.Types as TG
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
}
instants :: [(Text, String, TG.Grain, Int)]
instants =
[ ("right now", "((\x00E9pp )?most)|azonnal", TG.Second, 0 )
, ("today", "ma", TG.Day, 0 )
, ("tomorrow", "holnap", TG.Day, 1 )
, ("day after tomorrow", "holnaput\x00E1n", TG.Day, 2 )
, ("yesterday", "tegnap", TG.Day, 1 )
, ("day before yesterday", "tegnapel\x0151tt", TG.Day, 2 )
, ("end of month", "(a )?h\x00F3nap v\x00E9ge", TG.Month, 1 )
, ("end of year", "(az )?\x00E9v v\x00E9ge", 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
}
daysOfWeek :: [(Text, String)]
daysOfWeek =
[ ( "Monday" , "h\x00E9tf\x0151|h\x00E9t\\.?" )
, ( "Tuesday" , "kedd" )
, ( "Wednesday", "szerda|szer\\.?" )
, ( "Thursday" , "cs\x00FCt\x00F6rt\x00F6k|cs\x00FCt\\.?" )
, ( "Friday" , "p\x00E9ntek|p\x00E9n\\.?" )
, ( "Saturday" , "szombat|szom\\.?" )
, ( "Sunday" , "vas\x00E1rnap|vas\\.?" )
]
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" , "janu\x00E1r|jan\\.?" )
, ( "February" , "febru\x00E1r|febr?\\.?" )
, ( "March" , "m\x00E1rcius|m\x00E1rc?\\.?" )
, ( "April" , "\x00E1prilis|\x00E1pr\\.?" )
, ( "May" , "m\x00E1jus|m\x00E1j\\.?" )
, ( "June" , "j\x00FAnius|j\x00FAn\\.?" )
, ( "July" , "j\x00FAlius|j\x00FAl\\.?" )
, ( "August" , "augusztus|aug\\.?" )
, ( "September", "szeptember|szept?\\.?" )
, ( "October" , "okt\x00F3ber|okt\\.?" )
, ( "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
}
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
}
ruleCycleThisLastNext :: Rule
ruleCycleThisLastNext = Rule
{ name = "this|last|next <cycle>"
, pattern =
[ regex "(most|el\x0151z\x0151|m\x00FAlt|k\x00F6vetkez\x0151|j\x00F6v\x0151)"
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (match:_)):Token TimeGrain grain:_) ->
case Text.toLower match of
"most" -> tt $ cycleNth grain 0
"el\x0151z\x0151" -> tt . cycleNth grain $ 1
"m\x00FAlt" -> tt . cycleNth grain $ 1
"k\x00F6vetkez\x0151" -> tt $ cycleNth grain 1
"j\x00F6v\x0151" -> tt $ cycleNth grain 1
_ -> Nothing
_ -> Nothing
}
ruleNextDOW :: Rule
ruleNextDOW = Rule
{ name = "next <day-of-week>"
, pattern =
[ regex "j\x00F6v\x0151"
, Predicate isADayOfWeek
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ predNth 1 True 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
}
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
}
ruleTODLatent :: Rule
ruleTODLatent = Rule
{ name = "time-of-day (latent)"
, pattern =
[ Predicate $ and . sequence [isNumeralSafeToUse, isIntegerBetween 0 23]
]
, prod = \tokens -> case tokens of
(token:_) -> do
n <- getIntValue token
tt . mkLatent $ hour True n
_ -> Nothing
}
ruleTODAM :: Rule
ruleTODAM = Rule
{ name = "am <time-of-day>"
, pattern =
[ regex "(de\\.?|d\x00E9lel\x0151tt)"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt . timeOfDayAMPM td $ True
_ -> Nothing
}
ruleTODPM :: Rule
ruleTODPM = Rule
{ name = "pm <time-of-day>"
, pattern =
[ regex "(du\\.?|d\x00E9lut\x00E1n)"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt . timeOfDayAMPM td $ False
_ -> Nothing
}
ruleYYYYMMDD :: Rule
ruleYYYYMMDD = Rule
{ name = "yyyy.mm.dd"
, pattern =
[ regex "(\\d{2,4})\\s?[-\\.]\\s?(0?[1-9]|1[0-2])\\s?[-\\.]\\s?(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])\\s?[-\\.]\\s?(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
}
rulePartOfDays :: Rule
rulePartOfDays = Rule
{ name = "part of days"
, pattern =
[ regex "(reggel|d\x00E9lel\x0151tt|d\x00E9lben|d\x00E9lut\x00E1n|este|\x00E9jszaka)"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (match:_)):_) -> do
let (start, end) = case Text.toLower match of
"reggel" -> (hour False 6, hour False 10)
"d\x00E9lel\x0151tt" -> (hour False 08, hour False 12)
"d\x00E9lben" -> (hour False 12, hour False 13)
"d\x00E9lut\x00E1n" -> (hour False 12, hour False 18)
"este" -> (hour False 16, hour False 20)
_ -> (hour False 20, hour False 23)
td <- interval TTime.Open start end
tt . partOfDay $ td
_ -> Nothing
}
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
}
ruleSeasons :: Rule
ruleSeasons = Rule
{ name = "seasons"
, pattern =
[ regex "(ny\x00E1r|\x0151sz|t\x00E9l|tavasz)"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (match:_)):_) -> do
start <- case Text.toLower match of
"ny\x00E1r" -> Just $ monthDay 6 21
"\x0151sz" -> Just $ monthDay 9 23
"t\x00E9l" -> Just $ monthDay 12 21
"tavasz" -> Just $ monthDay 3 20
_ -> Nothing
end <- case Text.toLower match of
"ny\x00E1r" -> Just $ monthDay 9 23
"\x0151sz" -> Just $ monthDay 12 21
"t\x00E9l" -> Just $ monthDay 3 20
"tavasz" -> Just $ monthDay 6 21
_ -> Nothing
Token Time <$> interval TTime.Open start end
_ -> Nothing
}
rules :: [Rule]
rules =
[ ruleIntersect
, ruleMonthDOMNumeral
, ruleCycleThisLastNext
, ruleNextDOW
, ruleHHMM
, ruleHHMMSS
, ruleTODLatent
, ruleTODAM
, ruleTODPM
, ruleYYYYMMDD
, ruleMMDD
, rulePartOfDays
, ruleTimePOD
, ruleSeasons
]
++ ruleInstants
++ ruleDaysOfWeek
++ ruleMonths