Skip to content

Commit 82a54cd

Browse files
authored
Merge pull request #46 from javecs/feature/best-match
ベストマッチを選択する機能を追加しました。
2 parents 126a5f7 + f15de16 commit 82a54cd

9 files changed

Lines changed: 64 additions & 25 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ plugins {
1616
}
1717

1818
group 'xyz.javecs.tools'
19-
version '0.1.6'
19+
version '0.1.7'
2020

2121
apply plugin: 'kotlin'
2222
apply plugin: 'antlr'

src/main/kotlin/xyz/javecs/tools/text2expr/Text2Expr.kt

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,24 @@ class Text2Expr(rulePath: String = "rules") {
1818
}
1919

2020
fun eval(text: String, rendered: Boolean = false): String {
21-
rules.forEach {
22-
try {
23-
val evaluation = it.eval(text)
24-
if (evaluation.value != Double.NaN) return if (rendered) {
25-
val renderer = RuleRenderer(templates.templateOf(it.name))
26-
renderer.add("variables", evaluation.variables.map { Variable(it.key, it.value) }.toList())
27-
renderer.add("expr", evaluation.expr)
28-
renderer.add("text", text)
29-
renderer.add("value", evaluation.value)
30-
renderer.render()
31-
} else {
32-
evaluation.value.toString()
33-
}
34-
} catch (e: Exception) {
21+
val evaluated = rules.map { it.eval(text) }
22+
.filterNot { it.value == Double.NaN }
23+
.sortedByDescending { it.coverage }
24+
.toList()
25+
return if (evaluated.isEmpty()) {
26+
Calculator().eval(normalize(text)).value.toString()
27+
} else {
28+
val bestMatch = evaluated.first()
29+
if (rendered) {
30+
val renderer = RuleRenderer(templates.templateOf(bestMatch.rule))
31+
renderer.add("variables", bestMatch.variables.map { Variable(it.key, it.value) }.toList())
32+
renderer.add("expr", bestMatch.expr)
33+
renderer.add("text", text)
34+
renderer.add("value", bestMatch.value)
35+
renderer.render()
36+
} else {
37+
bestMatch.value.toString()
3538
}
3639
}
37-
return Calculator().eval(normalize(text)).value.toString()
3840
}
3941
}

src/main/kotlin/xyz/javecs/tools/text2expr/rules/RuleBuilder.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ private val NotFound = -2
1010
private val Optional = -3
1111
private val tokenizer = Tokenizer()
1212

13-
private fun coverage(scanned: Int, total: Int) = scanned.toDouble() / total.toDouble()
13+
private fun coverage(matched: Int, total: Int) = matched.toDouble() / total.toDouble()
1414

15-
data class Evaluation(val value: Number = Double.NaN, val expr: List<String> = ArrayList(), val variables: Map<String, Double> = HashMap(), val coverage: Double = 0.0)
15+
data class Evaluation(val value: Number = Double.NaN,
16+
val expr: List<String> = ArrayList(),
17+
val variables: Map<String, Double> = HashMap(),
18+
val coverage: Double = 0.0,
19+
val rule: String = "")
1620

1721
class RuleBuilder(source: String, val name: String = "") {
1822
private val parser = RuleParser()
@@ -53,16 +57,14 @@ class RuleBuilder(source: String, val name: String = "") {
5357
val tokens = tokenizer.tokenize(text)
5458
var offset = BaseOffset
5559
var remained = rule().size
56-
var coverage = 0.0
5760
rule().forEach {
5861
val (index, optional) = indexOf(it, tokens, start = offset + 1, end = Math.min(tokens.size - remained, tokens.lastIndex))
59-
if (index == NotFound) return Pair(false, coverage(index, tokens.size))
62+
if (index == NotFound) return Pair(false, 0.0)
6063
if (it.id.isNotEmpty()) recognizedId(Pair(it.id, if (optional) it.optionalValue().toString() else tokens[index].surface))
6164
if (!optional) offset = index
62-
coverage = coverage(index, tokens.size)
6365
remained--
6466
}
65-
return Pair(true, coverage)
67+
return Pair(true, coverage(rule().size, tokens.size))
6668
}
6769

6870
fun eval(text: String): Evaluation {
@@ -72,9 +74,9 @@ class RuleBuilder(source: String, val name: String = "") {
7274
return if (matched) {
7375
args.forEach { calc.eval(it) }
7476
expr().forEach { calc.eval(it) }
75-
Evaluation(calc.value, expr().toList(), calc.variables(), coverage)
77+
Evaluation(calc.value, expr().toList(), calc.variables(), coverage, name)
7678
} else {
77-
Evaluation()
79+
Evaluation(rule = name)
7880
}
7981
}
8082

src/test/kotlin/xyz/javecs/tools/text2expr/test/kotlin/RuleBuilderTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class RuleBuilderTest {
6565
val text = "1マイルは何キロメートルですか?"
6666
val (matched, coverage) = builder.matches(text)
6767
assertTrue(matched)
68-
assertEquals(0.5, coverage)
68+
assertEquals(0.375, coverage)
6969
assertEquals(1.60934, builder.eval(text).value)
7070
}
7171

src/test/kotlin/xyz/javecs/tools/text2expr/test/kotlin/Text2ExprTest.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,12 @@ class Text2ExprTest {
2626
assertEquals(reply, Text2Expr().eval("1足す1", rendered = true))
2727
}
2828

29+
@Test fun eval3() {
30+
val text = "1マイルは、ざっくりなんキロメートル?"
31+
assertEquals("1.60934", Text2Expr("test-best-match/rule1/rule2/rule3").eval(text))
32+
assertEquals("1.6093", Text2Expr("test-best-match/rule1/rule2").eval(text))
33+
assertEquals("1.609", Text2Expr("test-best-match/rule1").eval(text))
34+
assertEquals("1.6", Text2Expr("test-best-match").eval(text))
35+
}
36+
2937
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
x = P2?数(1)
2+
SF:マイル|"mile"
3+
SF:は
4+
P1:副詞, BF:ざっくり
5+
SF:なん
6+
SF:キロメートル|キロ|"km"
7+
8+
x*1.6
9+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
x = P2?数(1)
2+
SF:マイル|"mile"
3+
SF:は
4+
SF:なん
5+
SF:キロメートル|キロ|"km"
6+
7+
x*1.609
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
x = P2?数(1)
2+
SF:マイル|"mile"
3+
SF:は
4+
SF:キロメートル|キロ|"km"
5+
6+
x*1.6093
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
x = P2?数(1)
2+
SF:マイル|"mile"
3+
SF:キロメートル|キロ|"km"
4+
5+
x*1.60934

0 commit comments

Comments
 (0)