diff --git a/app/pages/classroom.vue b/app/pages/classroom.vue
index e18411c..e5dadb7 100644
--- a/app/pages/classroom.vue
+++ b/app/pages/classroom.vue
@@ -1170,6 +1170,7 @@
@@ -1359,6 +1360,20 @@ function similarity(a: string, b: string): number {
return 1 - distance / maxLen
}
+function allowedDistance(length: number): number {
+ if (length <= 12) return 0
+ if (length <= 24) return 1
+ if (length <= 36) return 2
+ return 3
+}
+
+function tightenedThreshold(length: number, base: number): number {
+ if (length >= 36) return Math.max(base, 0.9)
+ if (length >= 24) return Math.max(base, 0.92)
+ if (length >= 16) return Math.max(base, 0.94)
+ return Math.max(base, 0.97)
+}
+
const modules = shallowRef(learnModules)
type LessonSearchHit = {
@@ -3077,15 +3092,47 @@ const fieldStates = computed>(() => {
const alternatives = field.alternatives?.(scenario.value) ?? []
const options = [expected, ...alternatives].map(norm).filter(Boolean)
const normalizedAnswer = norm(answer)
- const best = options.length ? Math.max(...options.map(option => similarity(normalizedAnswer, option))) : 0
- const pass = answer ? best >= (field.threshold ?? 0.82) : false
+
+ let best = 0
+ let pass = false
+
+ if (answer && options.length) {
+ for (const option of options) {
+ if (!option) continue
+ if (normalizedAnswer === option) {
+ best = 1
+ pass = true
+ break
+ }
+
+ const distance = lev(normalizedAnswer, option)
+ const span = Math.max(option.length, normalizedAnswer.length, 1)
+ const score = 1 - distance / span
+ if (score > best) {
+ best = score
+ }
+
+ const allowance = allowedDistance(span)
+ if (allowance <= 0) continue
+
+ const threshold = tightenedThreshold(span, field.threshold ?? 0.82)
+ if (distance <= allowance && score >= threshold) {
+ pass = true
+ }
+ }
+
+ if (!pass && !best && options.length) {
+ best = Math.max(...options.map(option => similarity(normalizedAnswer, option)))
+ }
+ }
+
map[field.key] = {
key: field.key,
label: field.label,
expected,
answer,
similarity: answer ? best : 0,
- pass
+ pass: Boolean(answer && pass)
}
}
return map