Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions evap/static/ts/src/text-answer-warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,29 @@ function isTextMeaningless(text: string): boolean {
return text.length > 0 && ["", "ka", "na", "none", "keine", "keines", "keiner"].includes(text.replace(/\W/g, ""));
}

function containsPhrase(arr: string[], sub: string[]): boolean {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is very difficult to read, it does too many things at once. We should probably have something like

function matchesTriggerString(text: string, triggerString: string): boolean {
    const words = extractWords(text);
    const triggerWords = triggerString.split(" ");
    return isSubArray(triggerWords, words);
}

Then the isSubArray should also not be this complicated, it should use another function areArraysEqual, as I previously suggested

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that this also means that all of our custom "how do we handle weird text things" is separated from the entire "do the arrays match" logic

for (let i = 0; i <= arr.length - sub.length; i++) {
let j;
for (j = 0; j < sub.length; j++) {
if (j == sub.length - 1 && arr[i + j].length > sub[j].length) {
if (!arr[i + j].startsWith(sub[j])) break;
if (null !== RegExp("^[!?.]*$", "").exec(arr[i + j].substring(sub[j].length))) return true;
}
if (arr[i + j] !== sub[j]) break;
}
if (j >= sub.length) return true;
}
return false;
}

function matchesTriggerString(text: string, triggerString: string): boolean {
const words = text.split(" ");
const triggerWords = triggerString.split(" ");
Comment on lines +25 to +26
Copy link
Copy Markdown
Member

@niklasmohrin niklasmohrin Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting by a single space character means that we don't match if users accidentally put two spaces. We should split by any amount of whitespace (like what happens in Python when using str.split without passing any argument)

return containsPhrase(words, triggerWords);
}

function doesTextContainTriggerString(text: string, triggerStrings: string[]): boolean {
return triggerStrings.some(triggerString => text.includes(triggerString));
return triggerStrings.some(triggerString => matchesTriggerString(text, triggerString));
}

function updateTextareaWarning(textarea: HTMLTextAreaElement, textAnswerWarnings: string[][]) {
Expand Down Expand Up @@ -35,7 +56,7 @@ function updateTextareaWarning(textarea: HTMLTextAreaElement, textAnswerWarnings

export function initTextAnswerWarnings(textareas: NodeListOf<HTMLTextAreaElement>, textAnswerWarnings: string[][]) {
textAnswerWarnings = textAnswerWarnings.map(triggerStrings => triggerStrings.map(normalize));

console.log(textAnswerWarnings);
textareas.forEach(textarea => {
let warningDelayTimer: ReturnType<typeof setTimeout>;
textarea.addEventListener("input", () => {
Expand All @@ -53,4 +74,5 @@ export const testable = {
normalize,
isTextMeaningless,
doesTextContainTriggerString,
matchesTriggerString,
};
11 changes: 11 additions & 0 deletions evap/static/ts/tests/unit/text-answer-warnings.ts
Comment thread
AlexanderSchicktanz marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,14 @@ test.each([
const normalized = testable.normalize(text);
expect(testable.isTextMeaningless(normalized)).toBe(false);
});

test.each([
["", "s.o.", false],
["s.o.", "s.o.", true],
["s.o.s", "s.o.", false],
["Antwort: s.o.", "s.o.", true],
["siehe oben?!", "siehe oben", true],
])("matchesTriggerString(%p, %p) should return %p", (a, b, expected) => {
const result = testable.matchesTriggerString(a, b);
expect(result).toBe(expected);
});
Loading