Skip to content

Commit e62158b

Browse files
authored
Merge pull request #417 from mretallack/fix/calculator-npe
Fix: CalculatorSkill NPE when scoring operators in generateOutput
2 parents b91b6e5 + 0e062a3 commit e62158b

3 files changed

Lines changed: 59 additions & 2 deletions

File tree

app/src/main/kotlin/org/stypox/dicio/skills/calculator/CalculatorSkill.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.dicio.skill.skill.SkillInfo
77
import org.dicio.skill.skill.SkillOutput
88
import org.dicio.skill.standard.StandardRecognizerData
99
import org.dicio.skill.standard.StandardRecognizerSkill
10+
import org.dicio.skill.standard.util.MatchHelper
1011
import org.stypox.dicio.sentences.Sentences.Calculator
1112
import org.stypox.dicio.sentences.Sentences.CalculatorOperators
1213
import java.text.DecimalFormat
@@ -20,7 +21,8 @@ class CalculatorSkill(correspondingSkillInfo: SkillInfo, data: StandardRecognize
2021
operatorSection: StandardRecognizerData<CalculatorOperators>,
2122
text: String
2223
): CalculatorOperators? {
23-
val (score, result) = operatorSection.score(ctx, text)
24+
val helper = MatchHelper(ctx.parserFormatter, text)
25+
val (score, result) = operatorSection.score(helper, text)
2426
return if (score.scoreIn01Range() < 0.3) {
2527
null
2628
} else {

skill/src/main/java/org/dicio/skill/standard/StandardRecognizerData.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.dicio.skill.standard
33
import org.dicio.skill.context.SkillContext
44
import org.dicio.skill.skill.Specificity
55
import org.dicio.skill.standard.construct.Construct
6+
import org.dicio.skill.standard.util.MatchHelper
67
import org.dicio.skill.standard.util.initialMemToEnd
78

89
open class StandardRecognizerData<out T>(
@@ -11,7 +12,10 @@ open class StandardRecognizerData<out T>(
1112
private val sentencesWithId: List<Pair<String, Construct>>,
1213
) {
1314
fun score(ctx: SkillContext, input: String): Pair<StandardScore, T> {
14-
val helper = ctx.standardMatchHelper!! // surely != null, see its javadoc
15+
return score(ctx.standardMatchHelper!!, input)
16+
}
17+
18+
fun score(helper: MatchHelper, input: String): Pair<StandardScore, T> {
1519
val cumulativeWeight = helper.cumulativeWeight
1620

1721
var bestRes: Pair<String, StandardScore>? = null
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.dicio.skill.standard
2+
3+
import io.kotest.core.spec.style.StringSpec
4+
import io.kotest.matchers.shouldNotBe
5+
import org.dicio.skill.skill.Specificity
6+
import org.dicio.skill.standard.construct.WordConstruct
7+
import org.dicio.skill.standard.construct.CompositeConstruct
8+
import org.dicio.skill.standard.util.MatchHelper
9+
10+
/**
11+
* Regression test: StandardRecognizerData.score(MatchHelper, input) must work
12+
* without ctx.standardMatchHelper being set. This is needed when skills call
13+
* score() during generateOutput (e.g. CalculatorSkill matching operators).
14+
*/
15+
class StandardRecognizerDataTest : StringSpec({
16+
17+
"score with explicit MatchHelper does not require ctx" {
18+
// Build a simple recognizer that matches the word "plus"
19+
val construct = CompositeConstruct(
20+
listOf(WordConstruct("plus", false, false, 1.0f))
21+
)
22+
val data = StandardRecognizerData(
23+
specificity = Specificity.HIGH,
24+
converter = { input, sentenceId, _ -> sentenceId },
25+
sentencesWithId = listOf(Pair("plus_sentence", construct)),
26+
)
27+
28+
val helper = MatchHelper(parserFormatter = null, userInput = "plus")
29+
val (score, result) = data.score(helper, "plus")
30+
31+
score shouldNotBe null
32+
result shouldNotBe null
33+
}
34+
35+
"score with explicit MatchHelper returns low score for non-matching input" {
36+
val construct = CompositeConstruct(
37+
listOf(WordConstruct("plus", false, false, 1.0f))
38+
)
39+
val data = StandardRecognizerData(
40+
specificity = Specificity.HIGH,
41+
converter = { input, sentenceId, _ -> sentenceId },
42+
sentencesWithId = listOf(Pair("plus_sentence", construct)),
43+
)
44+
45+
val helper = MatchHelper(parserFormatter = null, userInput = "banana")
46+
val (score, _) = data.score(helper, "banana")
47+
48+
// should score poorly since "banana" doesn't match "plus"
49+
assert(score.scoreIn01Range() < 0.5f)
50+
}
51+
})

0 commit comments

Comments
 (0)