diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/Quantity.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/Quantity.scala index edb2da83..5681c8f3 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/Quantity.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/Quantity.scala @@ -30,13 +30,13 @@ case object Quantity extends Dimension with Rules { override val dimDependents: List[Dimension] = List(Numeral) } -case class QuantityData(v: Double, unit: String, dim: String, isLatent: Boolean = false) +case class QuantityData(v: Double, unit: String, dim: String, isLatent: Boolean = false, originValue: Option[Double] = None, originUnit: Option[String] = None) extends Resolvable with ResolvedValue { override def resolve(context: Context, options: Options): Option[(ResolvedValue, Boolean)] = - (QuantityValue(v, unit, dim), isLatent) + (QuantityValue(v, unit, dim, originValue, originUnit), isLatent) } -case class QuantityValue(v: Double, unit: String, dim: String) extends ResolvedValue { +case class QuantityValue(v: Double, unit: String, dim: String, originValue: Option[Double] = None, originUnit: Option[String] = None) extends ResolvedValue { override def schema: Option[String] = if ("温度".equalsIgnoreCase(dim)) Some(s"$v$unit") else Some(s"$v") } diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Rules.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Rules.scala index cc2ceaca..5f5b8434 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Rules.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Rules.scala @@ -27,21 +27,67 @@ trait Rules extends DimRules { val dim = "Distance" - private val scalar = Map( + private val scalar: Map[String, Double] = Map( "千米" -> 1000, "公里" -> 1000, "km" -> 1000, "米" -> 1, - "m" -> 1 + "m" -> 1, + "里地" -> 500, + "里" -> 500, + "英里" -> 1609.31, + "海里" -> 1853, + "分米" -> 0.1, + "dm" -> 0.1, + "厘米" -> 0.01, + "cm" -> 0.01, + "毫米" -> 0.001, + "mm" -> 0.001, + "微米" -> 1.0E-6, + "µm" -> 1.0E-6, + "纳米" -> 1.0E-9, + "nm" -> 1.0E-9, + "皮米" -> 1.0E-12, + "pm" -> 1.0E-12, + "丈" -> 3.33, + "尺" -> 0.333, + "英尺" -> 0.304794, + "寸" -> 0.0333, + "英寸" -> 0.025399, + "码" -> 0.914383, + "光年" -> 9.46E-15 ) + + def unit(s: String): String = s match { + case "千米" | "km" => "千米" + case "公里" => "公里" + case "公里" => "公里" + case "米" | "m" => "米" + case "里地" | "里" => "里" + case "英里" | "英里" => "英里" + case "海里" | "海里" => "海里" + case "分米" | "dm" => "分米" + case "厘米" | "cm" => "厘米" + case "毫米" | "mm" => "毫米" + case "微米" | "µm" => "微米" + case "纳米" | "nm" => "纳米" + case "皮米" | "pm" => "皮米" + case "丈" => "丈" + case "尺" => "尺" + case "英尺" => "英尺" + case "寸" => "寸" + case "英寸" => "英寸" + case "码" => "码" + case "光年" => "光年" + } val numberKm = Rule( name = " km", - pattern = List(isDimension(Numeral).predicate, "(?i)千米|米|公里|km|m".regex), + pattern = List(isDimension(Numeral).predicate, "(?i)千米|公里|km|里地|英里|海里|分米|dm|厘米|cm|毫米|mm|微米|µm|纳米|nm|皮米|pm|英尺|英寸|光年|丈|码|寸|尺|米|m|里".regex), prod = tokens { case Token(_, NumeralData(value, _, _, _, _, _)) :: Token(_, GroupMatch(s :: _)) :: _ => scalar.get(s.toLowerCase) match { - case Some(t) => Token(Distance, QuantityData(value * t, "米", dim)) + case Some(t) => Token(Distance, QuantityData(value * t, "米", dim, originValue = Some(value), originUnit = Some(unit(s)))) case None => throw new IllegalArgumentException(s"unknown scalar found: $s") } } diff --git a/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/ApiTest.scala b/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/ApiTest.scala index 46ea7e90..4b8b6951 100644 --- a/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/ApiTest.scala +++ b/duckling-fork-chinese/core/src/test/scala/com/xiaomi/duckling/ApiTest.scala @@ -24,6 +24,8 @@ import com.xiaomi.duckling.dimension.numeral.fraction.{Fraction, FractionData} import com.xiaomi.duckling.dimension.numeral.{DoubleSideIntervalValue, Numeral, NumeralValue, OpenIntervalValue} import com.xiaomi.duckling.dimension.ordinal.{Ordinal, OrdinalData} import com.xiaomi.duckling.dimension.quantity.QuantityValue +import com.xiaomi.duckling.dimension.quantity.distance.Distance +import com.xiaomi.duckling.dimension.quantity.velocity.Velocity import com.xiaomi.duckling.dimension.rating.Rating import com.xiaomi.duckling.dimension.season.Season import com.xiaomi.duckling.dimension.temperature.Temperature @@ -45,7 +47,7 @@ class ApiTest extends UnitSpec { it("should date") { val options = testOptions.copy(targets = Set(Numeral, Time, Duration, Date), full = false) - println(Api.analyze("1分9秒", testContext, options)) + println(Api.analyze("下个月的第一个星期一下雨吗", testContext, options)) } it("should age") { @@ -200,6 +202,21 @@ class ApiTest extends UnitSpec { } } } + + it("should distance") { + val options = testOptions.copy(targets = Set(Distance), full = false) + val queries = List("三十公里", "十海里", "一光年", "三毫米", "三英寸") + queries.foreach{ + query => + Api.analyze(query, testContext, options).foreach{ + answer => + answer.token.value match { + case data: QuantityValue => println(data) + case _ => println("error") + } + } + } + } } } diff --git a/duckling-fork-chinese/learning/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Examples.scala b/duckling-fork-chinese/learning/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Examples.scala index 4a1eaa9f..a5915762 100644 --- a/duckling-fork-chinese/learning/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Examples.scala +++ b/duckling-fork-chinese/learning/src/main/scala/com/xiaomi/duckling/dimension/quantity/distance/Examples.scala @@ -22,8 +22,25 @@ import com.xiaomi.duckling.dimension.quantity.QuantityValue object Examples extends DimExamples { override def pairs: List[(Types.ResolvedValue, List[String])] = List( - (QuantityValue(3000, "米", "Distance"), List("3千米", "三公里", "3km")), - (QuantityValue(3000, "米", "Distance"), List("3000米", "3000m")) + (QuantityValue(3000, "米", "Distance", originValue = Some(3), originUnit = Some("千米")), List("3千米", "3km")), + (QuantityValue(3000, "米", "Distance", originValue = Some(3), originUnit = Some("公里")), List("三公里")), + (QuantityValue(3000, "米", "Distance", originValue = Some(3000), originUnit = Some("米")), List("3000米", "3000m")), + (QuantityValue(1000, "米", "Distance", originValue = Some(2), originUnit = Some("里")), List("二里地", "2里")), + (QuantityValue(16093.1, "米", "Distance", originValue = Some(10), originUnit = Some("英里")), List("十英里", "10英里")), + (QuantityValue(5559, "米", "Distance", originValue = Some(3), originUnit = Some("海里")), List("三海里", "3海里")), + (QuantityValue(0.1, "米", "Distance", originValue = Some(1), originUnit = Some("分米")), List("一分米", "1dm")), + (QuantityValue(0.1, "米", "Distance", originValue = Some(10), originUnit = Some("厘米")), List("十厘米", "10cm")), + (QuantityValue(0.003, "米", "Distance", originValue = Some(3), originUnit = Some("毫米")), List("三毫米", "3mm")), + (QuantityValue(3.0E-6, "米", "Distance", originValue = Some(3), originUnit = Some("微米")), List("3微米", "3µm")), + (QuantityValue(3.0E-9, "米", "Distance", originValue = Some(3), originUnit = Some("纳米")), List("3纳米", "3nm")), + (QuantityValue(1.0E-11, "米", "Distance", originValue = Some(10), originUnit = Some("皮米")), List("十皮米", "10pm")), + (QuantityValue(6.66, "米", "Distance", originValue = Some(2), originUnit = Some("丈")), List("两丈")), + (QuantityValue(0.999, "米", "Distance", originValue = Some(3), originUnit = Some("尺")), List("三尺")), + (QuantityValue(0.304794, "米", "Distance", originValue = Some(1), originUnit = Some("英尺")), List("一英尺")), + (QuantityValue(0.0999, "米", "Distance", originValue = Some(3), originUnit = Some("寸")), List("三寸")), + (QuantityValue(0.025399, "米", "Distance", originValue = Some(1), originUnit = Some("英寸")), List("1英寸")), + (QuantityValue(0.914383, "米", "Distance", originValue = Some(1), originUnit = Some("码")), List("1码")), + (QuantityValue(9.46E-14, "米", "Distance", originValue = Some(10), originUnit = Some("光年")), List("10光年")) ) override val dimension: Dimension = Distance