diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Rules.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Rules.scala index a1644e79..cd8779fe 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Rules.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Rules.scala @@ -133,7 +133,7 @@ trait Rules extends DimRules { prod = tokens { case Token(Time, td: TimeData) :: Token(Ordinal, od: OrdinalData) - :: Token(TimeGrain, GrainData(g, _)) :: _ if td.timeGrain > g && g == Grain.Day && !od.ge => + :: Token(TimeGrain, GrainData(g, _, _)) :: _ if td.timeGrain > g && g == Grain.Day && !od.ge => val predicate = if (od.value >= 0) { val ov = if(od.value > 0) od.value.toInt -1 else 0 @@ -157,7 +157,7 @@ trait Rules extends DimRules { prod = tokens { case Token(Time, td: TimeData) :: _ :: Token(Ordinal, od: OrdinalData) - :: Token(TimeGrain, GrainData(g, _)) :: _ if td.timeGrain > g && g == Grain.Day && !od.ge => + :: Token(TimeGrain, GrainData(g, _, _)) :: _ if td.timeGrain > g && g == Grain.Day && !od.ge => val predicate = if (od.value >= 0) { val ov = if(od.value > 0) od.value.toInt -1 else 0 @@ -237,7 +237,7 @@ trait Rules extends DimRules { pattern = List("(这个?|今个?|本|下+一?个?|上+一?个?|去|昨|明|大*前|大*后)".regex, isDimension(TimeGrain).predicate), prod = tokens { - case Token(_, GroupMatch(s :: _)) :: Token(TimeGrain, GrainData(g, false)) :: _ => + case Token(_, GroupMatch(s :: _)) :: Token(TimeGrain, GrainData(g, false, _)) :: _ => val td: Option[TimeData] = s(0) match { case '这' => cycleNthThis(0, g, Year, Month, Hour, Week) case '今' => cycleNthThis(0, g, Year, Month, Day) diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/Rules.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/Rules.scala index ce235379..ef67e7e5 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/Rules.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/Rules.scala @@ -43,7 +43,7 @@ trait Rules extends DimRules { } val tp: TokensProduction = { - case t1 :: Token(TimeGrain, GrainData(g, latent)) :: _ => + case t1 :: Token(TimeGrain, GrainData(g, latent, _)) :: _ => if (isDimension(UnitNumber)(t1) && !compatibleWithUnitNumber(g)) None else { if (isDimension(Numeral)(t1) && g == Month) None @@ -95,7 +95,7 @@ trait Rules extends DimRules { name = "few ", pattern = List("几个?".regex, isDimension(TimeGrain).predicate), prod = optTokens { - case (options: Options, _ :: Token(TimeGrain, GrainData(g, _)) :: _) if options.timeOptions.durationFuzzyOn => + case (options: Options, _ :: Token(TimeGrain, GrainData(g, _, _)) :: _) if options.timeOptions.durationFuzzyOn => Token(Duration, DurationData( options.timeOptions.durationFuzzyValue, g, @@ -118,7 +118,7 @@ trait Rules extends DimRules { name = "number.number grain", pattern = List("(\\d+)\\.(\\d+)".regex, isDimension(TimeGrain).predicate), prod = tokens { - case Token(_, GroupMatch(_ :: integer :: decimal :: _)) :: Token(_, GrainData(g, false)) :: _ => + case Token(_, GroupMatch(_ :: integer :: decimal :: _)) :: Token(_, GrainData(g, false, _)) :: _ => (for { i <- parseInt(integer).toOption d <- parseInt(decimal).toOption @@ -144,7 +144,7 @@ trait Rules extends DimRules { name = "half a ", pattern = List("半个?".regex, isDimension(TimeGrain).predicate), prod = tokens { - case _ :: Token(TimeGrain, GrainData(grain, _)) :: _ => + case _ :: Token(TimeGrain, GrainData(grain, _, _)) :: _ => for (d <- timesOneAndAHalf(grain, 0)) yield Token(Duration, d) } ) @@ -170,7 +170,7 @@ trait Rules extends DimRules { name = " half ", pattern = List(isDimension(UnitNumber).predicate, "半".regex, isDimension(TimeGrain).predicate), prod = tokens { - case t1 :: _ :: Token(TimeGrain, GrainData(g, _)) :: _ => + case t1 :: _ :: Token(TimeGrain, GrainData(g, _, _)) :: _ => for { i <- getIntValue(t1) d <- timesOneAndAHalf(g, i.toInt) @@ -203,7 +203,7 @@ trait Rules extends DimRules { isNotLatentDuration.predicate ), prod = tokens { - case t1 :: Token(TimeGrain, GrainData(g, _)) :: _ :: Token(_, dd@DurationData(_, dg, _, _, _)) :: _ + case t1 :: Token(TimeGrain, GrainData(g, _, _)) :: _ :: Token(_, dd@DurationData(_, dg, _, _, _)) :: _ if g > dg && g != Month => for (i <- getIntValue(t1)) yield Token(Duration, DurationData(i.toInt, g, schema = durationSchema(i.toInt.toString, g)) + dd) } @@ -224,8 +224,8 @@ trait Rules extends DimRules { isDimension(TimeGrain).predicate ), prod = tokens { - case t1 :: Token(TimeGrain, GrainData(g0, _)) :: Token(DigitSequence, DigitSequenceData(s, _, _)) :: Token(TimeGrain, GrainData(g1, _)) :: _ - if g0 > g1 => + case t1 :: Token(TimeGrain, GrainData(g0, _, raw)) :: Token(DigitSequence, DigitSequenceData(s, _, _)) :: Token(TimeGrain, GrainData(g1, _, _)) :: _ + if g0 > g1 && raw != "点" => for (i <- getIntValue(t1)) yield Token(Duration, DurationData(i.toInt, g0, schema = durationSchema(i.toString, g0)) + DurationData(s.toInt, g1, schema = durationSchema(s.toInt.toString, g1))) } ) diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/package.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/package.scala index b3bc3c64..3b7948a9 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/package.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/duration/package.scala @@ -60,7 +60,7 @@ package object duration { } def isMonth: Predicate = { - case Token(TimeGrain, GrainData(Month, _)) => true + case Token(TimeGrain, GrainData(Month, _, _)) => true } def isNotLatentDuration: Predicate = { @@ -72,7 +72,7 @@ package object duration { } def isNotLatentGrain: Predicate = { - case Token(TimeGrain, GrainData(_, latent)) => !latent + case Token(TimeGrain, GrainData(_, latent, _)) => !latent } private def grainShorthand(grain: Grain): String = { diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/Rules.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/Rules.scala index 3a7c8916..eb7e75ed 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/Rules.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/Rules.scala @@ -41,7 +41,7 @@ trait Rules extends DimRules { case (name, regexPattern, grain) => Rule(name = name, pattern = List(regexPattern.regex), prod = singleRegexMatch { case s => - Token(TimeGrain, GrainData(grain, latentExpr.contains(s))) + Token(TimeGrain, GrainData(grain, latentExpr.contains(s), s)) }) } } diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/TimeGrain.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/TimeGrain.scala index 2da7a7c7..4af7c6ab 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/TimeGrain.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/grain/TimeGrain.scala @@ -25,7 +25,7 @@ case object TimeGrain extends Dimension with Rules { override val name: String = "TimeGrain" } -case class GrainData(grain: Grain, latent: Boolean = false) extends Resolvable with ResolvedValue { +case class GrainData(grain: Grain, latent: Boolean = false, raw: String) extends Resolvable with ResolvedValue { override def resolve(context: Context, options: Options): Option[(ResolvedValue, Boolean)] = { (this, false) diff --git a/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/dimension/time/duration/DurationTest.scala b/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/dimension/time/duration/DurationTest.scala new file mode 100644 index 00000000..bcd12dc5 --- /dev/null +++ b/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/dimension/time/duration/DurationTest.scala @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Xiaomi and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.xiaomi.duckling.dimension.time.duration + +import com.xiaomi.duckling.Api.analyze +import com.xiaomi.duckling.ranking.Testing._ +import com.xiaomi.duckling.UnitSpec + +class DurationTest extends UnitSpec { + + private val options = testOptions.copy(targets = Set(Duration)) + + describe("duration cases") { + + it("零一年五月八月") { + val a = analyze("七点05分", testContext, options) + a shouldBe empty + } + } +}