Refactor and test language API

This commit is contained in:
IRBorisov 2023-11-20 18:03:34 +03:00
parent c5d80328ef
commit edda87c7ee
4 changed files with 116 additions and 24 deletions

View File

@ -11,7 +11,7 @@ import { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDoubleDownIcon, CrossI
import { useConceptTheme } from '../context/ThemeContext'; import { useConceptTheme } from '../context/ThemeContext';
import useConceptText from '../hooks/useConceptText'; import useConceptText from '../hooks/useConceptText';
import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '../models/language'; import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '../models/language';
import { getCompatibleGrams, matchWordForm, parseGrammemes } from '../models/languageAPI'; import { getCompatibleGrams, wordFormEquals, parseGrammemes } from '../models/languageAPI';
import { IConstituenta, TermForm } from '../models/rsform'; import { IConstituenta, TermForm } from '../models/rsform';
import { colorfgGrammeme } from '../utils/color'; import { colorfgGrammeme } from '../utils/color';
import { labelGrammeme } from '../utils/labels'; import { labelGrammeme } from '../utils/labels';
@ -81,7 +81,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
}; };
setForms(forms => [ setForms(forms => [
newForm, newForm,
...forms.filter(value => !matchWordForm(value, newForm)) ...forms.filter(value => !wordFormEquals(value, newForm))
]); ]);
} }
@ -143,7 +143,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
text: form.text, text: form.text,
grams: parseGrammemes(form.grams).filter(gram => SelectorGrammemesList.find(item => item === gram as Grammeme)) grams: parseGrammemes(form.grams).filter(gram => SelectorGrammemesList.find(item => item === gram as Grammeme))
} }
if (newForm.grams.length === 2 && !lexeme.some(test => matchWordForm(test, newForm))) { if (newForm.grams.length === 2 && !lexeme.some(test => wordFormEquals(test, newForm))) {
lexeme.push(newForm); lexeme.push(newForm);
} }
}); });

View File

@ -1,13 +1,96 @@
import { Grammeme } from './language'; import { Case, Grammeme, NounGrams, Plurality, VerbGrams } from './language';
import { parseEntityReference, parseGrammemes, parseSyntacticReference } from './languageAPI'; import {
getCompatibleGrams, grammemeCompare,
parseEntityReference, parseGrammemes, parseSyntacticReference,
wordFormEquals
} from './languageAPI';
describe('Testing wordform equality', () => {
test('empty input',
() => {
expect(wordFormEquals({text: '', grams: []}, {text: '', grams: []})).toEqual(true);
expect(wordFormEquals({text: '', grams: []}, {text: '11', grams: []})).toEqual(true);
expect(wordFormEquals({text: '11', grams: []}, {text: '', grams: []})).toEqual(true);
expect(wordFormEquals({text: '11', grams: []}, {text: '42', grams: []})).toEqual(true);
expect(wordFormEquals({text: '', grams: ['nomn']}, {text: '', grams: []})).toEqual(false);
expect(wordFormEquals({text: '11', grams: ['nomn']}, {text: '11', grams: []})).toEqual(false);
expect(wordFormEquals({text: '', grams: []}, {text: '', grams: ['nomn']})).toEqual(false);
expect(wordFormEquals({text: '11', grams: []}, {text: '11', grams: ['nomn']})).toEqual(false);
});
test('regular grammemes',
() => {
expect(wordFormEquals({text: '', grams: ['nomn']}, {text: '', grams: ['nomn']})).toEqual(true);
expect(wordFormEquals({text: '', grams: ['nomn']}, {text: '', grams: ['sing']})).toEqual(false);
expect(wordFormEquals({text: '', grams: ['nomn', 'sing']}, {text: '', grams: ['nomn', 'sing']})).toEqual(true);
expect(wordFormEquals({text: '', grams: ['nomn', 'sing']}, {text: '11', grams: ['nomn', 'sing']})).toEqual(true);
expect(wordFormEquals({text: '11', grams: ['nomn', 'sing']}, {text: '', grams: ['nomn', 'sing']})).toEqual(true);
expect(wordFormEquals({text: '11', grams: ['nomn', 'sing']}, {text: '11', grams: ['nomn', 'sing']})).toEqual(true);
expect(wordFormEquals({text: '42', grams: ['nomn', 'sing']}, {text: '11', grams: ['nomn', 'sing']})).toEqual(true);
expect(wordFormEquals({text: '', grams: ['nomn', 'sing']}, {text: '', grams: ['sing', 'nomn']})).toEqual(false);
expect(wordFormEquals({text: '', grams: ['nomn', 'sing']}, {text: '', grams: ['nomn']})).toEqual(false);
expect(wordFormEquals({text: '', grams: ['nomn', 'nomn']}, {text: '', grams: ['nomn']})).toEqual(false);
});
test('custom grammemes',
() => {
expect(wordFormEquals({text: '', grams: ['с1']}, {text: '', grams: ['с1']})).toEqual(true);
expect(wordFormEquals({text: '', grams: ['с1']}, {text: '', grams: ['с2']})).toEqual(false);
expect(wordFormEquals({text: '', grams: ['sing']}, {text: '', grams: ['с1']})).toEqual(false);
});
});
describe('Testing grammeme ordering', () => {
test('empty input',
() => {
expect(grammemeCompare('', '')).toEqual(0);
expect(grammemeCompare(' ', ' ')).toEqual(0);
expect(grammemeCompare('', '123')).toBeLessThan(0);
expect(grammemeCompare('123', '')).toBeGreaterThan(0);
});
test('regular grammemes',
() => {
expect(grammemeCompare('NOUN', 'NOUN')).toEqual(0);
expect(grammemeCompare('NOUN', Grammeme.NOUN)).toEqual(0);
expect(grammemeCompare(Grammeme.sing, Grammeme.plur)).toBeLessThan(0);
expect(grammemeCompare('sing', 'plur')).toBeLessThan(0);
expect(grammemeCompare('plur', 'sing')).toBeGreaterThan(0);
expect(grammemeCompare('NOUN', 'ADJF')).toBeLessThan(0);
expect(grammemeCompare('ADJF', 'NOUN')).toBeGreaterThan(0);
expect(grammemeCompare('ADJS', 'NOUN')).toBeGreaterThan(0);
expect(grammemeCompare('ADJS', 'ADJF')).toBeGreaterThan(0);
expect(grammemeCompare('loct', 'ablt')).toBeGreaterThan(0);
expect(grammemeCompare('ablt', 'accs')).toBeGreaterThan(0);
expect(grammemeCompare('accs', 'datv')).toBeGreaterThan(0);
expect(grammemeCompare('datv', 'gent')).toBeGreaterThan(0);
expect(grammemeCompare('gent', 'nomn')).toBeGreaterThan(0);
});
test('custom grammemes',
() => {
expect(grammemeCompare('noun', 'noun')).toEqual(0);
expect(grammemeCompare('NOUN', 'noun')).toBeLessThan(0);
expect(grammemeCompare('PRTF', 'noun')).toBeLessThan(0);
expect(grammemeCompare('noun', 'NOUN')).toBeGreaterThan(0);
expect(grammemeCompare('aab', 'aaa')).toBeGreaterThan(0);
expect(grammemeCompare('aaa', 'aab')).toBeLessThan(0);
expect(grammemeCompare('test', 'abcd')).toBeGreaterThan(0);
});
});
describe('Testing grammeme parsing', () => { describe('Testing grammeme parsing', () => {
test('empty input', test('empty input',
() => { () => {
expect(parseGrammemes('').length).toBe(0); expect(parseGrammemes('')).toStrictEqual([]);
expect(parseGrammemes(' ').length).toBe(0); expect(parseGrammemes(' ')).toStrictEqual([]);
expect(parseGrammemes(' , ').length).toBe(0); expect(parseGrammemes(' , ')).toStrictEqual([]);
}); });
test('regular grammemes', test('regular grammemes',
@ -15,12 +98,29 @@ describe('Testing grammeme parsing', () => {
expect(parseGrammemes('NOUN')).toStrictEqual([Grammeme.NOUN]); expect(parseGrammemes('NOUN')).toStrictEqual([Grammeme.NOUN]);
expect(parseGrammemes('sing,nomn')).toStrictEqual([Grammeme.sing, Grammeme.nomn]); expect(parseGrammemes('sing,nomn')).toStrictEqual([Grammeme.sing, Grammeme.nomn]);
expect(parseGrammemes('nomn,sing')).toStrictEqual([Grammeme.sing, Grammeme.nomn]); expect(parseGrammemes('nomn,sing')).toStrictEqual([Grammeme.sing, Grammeme.nomn]);
});
test('custom grammemes',
() => {
expect(parseGrammemes('nomn,invalid,sing')).toStrictEqual([Grammeme.sing, Grammeme.nomn, 'invalid']); expect(parseGrammemes('nomn,invalid,sing')).toStrictEqual([Grammeme.sing, Grammeme.nomn, 'invalid']);
expect(parseGrammemes('invalid,test')).toStrictEqual(['invalid', 'test']); expect(parseGrammemes('invalid,test')).toStrictEqual(['invalid', 'test']);
}); });
}); });
describe('Testing grammeme compatibility', () => {
test('empty input',
() => {
expect(getCompatibleGrams([])).toStrictEqual([...VerbGrams, ...NounGrams]);
});
test('regular grammemes',
() => {
expect(getCompatibleGrams([Grammeme.NOUN])).toStrictEqual([...Case, ...Plurality]);
});
});
describe('Testing reference parsing', () => { describe('Testing reference parsing', () => {
test('entity reference', test('entity reference',
() => { () => {

View File

@ -7,7 +7,7 @@ import { GramData, Grammeme, GrammemeGroups, IEntityReference, ISyntacticReferen
/** /**
* Equality comparator for {@link IWordForm}. Compares a set of Grammemes attached to wordforms * Equality comparator for {@link IWordForm}. Compares a set of Grammemes attached to wordforms
*/ */
export function matchWordForm(left: IWordForm, right: IWordForm): boolean { export function wordFormEquals(left: IWordForm, right: IWordForm): boolean {
if (left.grams.length !== right.grams.length) { if (left.grams.length !== right.grams.length) {
return false; return false;
} }
@ -19,18 +19,10 @@ export function matchWordForm(left: IWordForm, right: IWordForm): boolean {
return true; return true;
} }
function parseSingleGrammeme(text: string): GramData {
if (Object.values(Grammeme).includes(text as Grammeme)) {
return text as Grammeme;
} else {
return text;
}
}
/** /**
* Compares {@link GramData} based on Grammeme enum and alpha order for strings. * Compares {@link GramData} based on Grammeme enum and alpha order for strings.
*/ */
export function compareGrammemes(left: GramData, right: GramData): number { export function grammemeCompare(left: GramData, right: GramData): number {
const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left as Grammeme); const indexLeft = Object.values(Grammeme).findIndex(gram => gram === left as Grammeme);
const indexRight = Object.values(Grammeme).findIndex(gram => gram === right as Grammeme); const indexRight = Object.values(Grammeme).findIndex(gram => gram === right as Grammeme);
if (indexLeft === -1 && indexRight === -1) { if (indexLeft === -1 && indexRight === -1) {
@ -51,12 +43,12 @@ export function parseGrammemes(termForm: string): GramData[] {
const result: GramData[] = []; const result: GramData[] = [];
const chunks = termForm.split(','); const chunks = termForm.split(',');
chunks.forEach(chunk => { chunks.forEach(chunk => {
chunk = chunk.trim(); const gram = chunk.trim();
if (chunk !== '') { if (gram !== '') {
result.push(parseSingleGrammeme(chunk)); result.push(gram);
} }
}); });
return result.sort(compareGrammemes); return result.sort(grammemeCompare);
} }
/** /**

View File

@ -4,7 +4,7 @@
import { LayoutTypes } from 'reagraph'; import { LayoutTypes } from 'reagraph';
import { type GramData, Grammeme, ReferenceType } from '../models/language'; import { type GramData, Grammeme, ReferenceType } from '../models/language';
import { compareGrammemes } from '../models/languageAPI'; import { grammemeCompare } from '../models/languageAPI';
import { CstType } from '../models/rsform'; import { CstType } from '../models/rsform';
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph'; import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
import { labelGrammeme, labelReferenceType } from './labels'; import { labelGrammeme, labelReferenceType } from './labels';
@ -61,7 +61,7 @@ export interface IGrammemeOption {
* Compares {@link IGrammemeOption} based on Grammeme comparison. * Compares {@link IGrammemeOption} based on Grammeme comparison.
*/ */
export function compareGrammemeOptions(left: IGrammemeOption, right: IGrammemeOption): number { export function compareGrammemeOptions(left: IGrammemeOption, right: IGrammemeOption): number {
return compareGrammemes(left.value, right.value); return grammemeCompare(left.value, right.value);
} }
/** /**