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 useConceptText from '../hooks/useConceptText';
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 { colorfgGrammeme } from '../utils/color';
import { labelGrammeme } from '../utils/labels';
@ -81,7 +81,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
};
setForms(forms => [
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,
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);
}
});

View File

@ -1,13 +1,96 @@
import { Grammeme } from './language';
import { parseEntityReference, parseGrammemes, parseSyntacticReference } from './languageAPI';
import { Case, Grammeme, NounGrams, Plurality, VerbGrams } from './language';
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', () => {
test('empty input',
() => {
expect(parseGrammemes('').length).toBe(0);
expect(parseGrammemes(' ').length).toBe(0);
expect(parseGrammemes(' , ').length).toBe(0);
expect(parseGrammemes('')).toStrictEqual([]);
expect(parseGrammemes(' ')).toStrictEqual([]);
expect(parseGrammemes(' , ')).toStrictEqual([]);
});
test('regular grammemes',
@ -15,12 +98,29 @@ describe('Testing grammeme parsing', () => {
expect(parseGrammemes('NOUN')).toStrictEqual([Grammeme.NOUN]);
expect(parseGrammemes('sing,nomn')).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('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', () => {
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
*/
export function matchWordForm(left: IWordForm, right: IWordForm): boolean {
export function wordFormEquals(left: IWordForm, right: IWordForm): boolean {
if (left.grams.length !== right.grams.length) {
return false;
}
@ -19,18 +19,10 @@ export function matchWordForm(left: IWordForm, right: IWordForm): boolean {
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.
*/
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 indexRight = Object.values(Grammeme).findIndex(gram => gram === right as Grammeme);
if (indexLeft === -1 && indexRight === -1) {
@ -51,12 +43,12 @@ export function parseGrammemes(termForm: string): GramData[] {
const result: GramData[] = [];
const chunks = termForm.split(',');
chunks.forEach(chunk => {
chunk = chunk.trim();
if (chunk !== '') {
result.push(parseSingleGrammeme(chunk));
const gram = chunk.trim();
if (gram !== '') {
result.push(gram);
}
});
return result.sort(compareGrammemes);
return result.sort(grammemeCompare);
}
/**

View File

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