mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor models: split API in separate module
This commit is contained in:
parent
643f43c819
commit
97bec834f0
|
@ -1,4 +1,5 @@
|
||||||
import { IConstituenta, isMockCst } from '../../models/rsform';
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { isMockCst } from '../../models/rsformAPI';
|
||||||
import { colorfgCstStatus,IColorTheme } from '../../utils/color';
|
import { colorfgCstStatus,IColorTheme } from '../../utils/color';
|
||||||
import { describeExpressionStatus } from '../../utils/labels';
|
import { describeExpressionStatus } from '../../utils/labels';
|
||||||
import ConceptTooltip from '../Common/ConceptTooltip';
|
import ConceptTooltip from '../Common/ConceptTooltip';
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
import { CstMatchMode } from '../../models/miscelanious';
|
import { CstMatchMode } from '../../models/miscelanious';
|
||||||
import { IConstituenta, matchConstituenta } from '../../models/rsform';
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { matchConstituenta } from '../../models/rsformAPI';
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
import { describeConstituenta } from '../../utils/labels';
|
import { describeConstituenta } from '../../utils/labels';
|
||||||
import ConceptSearch from '../Common/ConceptSearch';
|
import ConceptSearch from '../Common/ConceptSearch';
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { ErrorInfo } from '../components/BackendError';
|
||||||
import { matchLibraryItem } from '../models/library';
|
import { matchLibraryItem } from '../models/library';
|
||||||
import { ILibraryItem } from '../models/library';
|
import { ILibraryItem } from '../models/library';
|
||||||
import { ILibraryFilter } from '../models/miscelanious';
|
import { ILibraryFilter } from '../models/miscelanious';
|
||||||
import { IRSForm, IRSFormCreateData, IRSFormData, loadRSFormData } from '../models/rsform';
|
import { IRSForm, IRSFormCreateData, IRSFormData } from '../models/rsform';
|
||||||
|
import { loadRSFormData } from '../models/rsformAPI';
|
||||||
import { DataCallback, deleteLibraryItem, getLibrary, getRSFormDetails, getTemplates, postCloneLibraryItem, postNewRSForm } from '../utils/backendAPI';
|
import { DataCallback, deleteLibraryItem, getLibrary, getRSFormDetails, getTemplates, postCloneLibraryItem, postNewRSForm } from '../utils/backendAPI';
|
||||||
import { useAuth } from './AuthContext';
|
import { useAuth } from './AuthContext';
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ import TextArea from '../../components/Common/TextArea';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
||||||
import { useLibrary } from '../../context/LibraryContext';
|
import { useLibrary } from '../../context/LibraryContext';
|
||||||
import { applyFilterCategory, CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
|
import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
|
import { applyFilterCategory } from '../../models/rsformAPI';
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
export interface ITemplateState {
|
export interface ITemplateState {
|
||||||
templateID?: number
|
templateID?: number
|
||||||
|
|
|
@ -7,7 +7,8 @@ import Modal, { ModalProps } from '../../components/Common/Modal';
|
||||||
import HelpRSTemplates from '../../components/Help/HelpRSTemplates';
|
import HelpRSTemplates from '../../components/Help/HelpRSTemplates';
|
||||||
import { HelpIcon } from '../../components/Icons';
|
import { HelpIcon } from '../../components/Icons';
|
||||||
import usePartialUpdate from '../../hooks/usePartialUpdate';
|
import usePartialUpdate from '../../hooks/usePartialUpdate';
|
||||||
import { CstType, ICstCreateData, inferTemplatedType, IRSForm, substituteTemplateArgs } from '../../models/rsform';
|
import { CstType, ICstCreateData, IRSForm } from '../../models/rsform';
|
||||||
|
import { inferTemplatedType, substituteTemplateArgs } from '../../models/rslangAPI';
|
||||||
import { createAliasFor, validateCstAlias } from '../../utils/misc';
|
import { createAliasFor, validateCstAlias } from '../../utils/misc';
|
||||||
import ArgumentsTab, { IArgumentsState } from './ArgumentsTab';
|
import ArgumentsTab, { IArgumentsState } from './ArgumentsTab';
|
||||||
import ConstituentaTab from './ConstituentaTab';
|
import ConstituentaTab from './ConstituentaTab';
|
||||||
|
|
|
@ -14,7 +14,8 @@ import {
|
||||||
parseSyntacticReference, ReferenceType
|
parseSyntacticReference, ReferenceType
|
||||||
} from '../../models/language';
|
} from '../../models/language';
|
||||||
import { CstMatchMode } from '../../models/miscelanious';
|
import { CstMatchMode } from '../../models/miscelanious';
|
||||||
import { IConstituenta, matchConstituenta } from '../../models/rsform';
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { matchConstituenta } from '../../models/rsformAPI';
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors';
|
import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors';
|
||||||
import ReferenceTypeButton from './ReferenceTypeButton';
|
import ReferenceTypeButton from './ReferenceTypeButton';
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { type ErrorInfo } from '../components/BackendError';
|
import { type ErrorInfo } from '../components/BackendError';
|
||||||
import { IRSForm, IRSFormData, loadRSFormData } from '../models/rsform'
|
import { IRSForm, IRSFormData } from '../models/rsform'
|
||||||
|
import { loadRSFormData } from '../models/rsformAPI';
|
||||||
import { getRSFormDetails } from '../utils/backendAPI';
|
import { getRSFormDetails } from '../utils/backendAPI';
|
||||||
|
|
||||||
export function useRSFormDetails({ target }: { target?: string }) {
|
export function useRSFormDetails({ target }: { target?: string }) {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { Graph } from '../utils/Graph'
|
import { Graph } from '../utils/Graph'
|
||||||
import { TextMatcher } from '../utils/utils'
|
|
||||||
import { ILibraryUpdateData } from './library'
|
import { ILibraryUpdateData } from './library'
|
||||||
import { ILibraryItem } from './library'
|
import { ILibraryItem } from './library'
|
||||||
import { CstMatchMode } from './miscelanious'
|
import { IArgumentInfo, ParsingStatus, ValueClass } from './rslang'
|
||||||
import { IArgumentInfo, IArgumentValue, ParsingStatus, ValueClass } from './rslang'
|
|
||||||
|
|
||||||
export enum CstType {
|
export enum CstType {
|
||||||
BASE = 'basic',
|
BASE = 'basic',
|
||||||
|
@ -141,209 +139,4 @@ export interface IRSFormUploadData {
|
||||||
load_metadata: boolean
|
load_metadata: boolean
|
||||||
file: File
|
file: File
|
||||||
fileName: string
|
fileName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== API =================
|
|
||||||
export function extractGlobals(expression: string): Set<string> {
|
|
||||||
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inferTemplatedType(templateType: CstType, args: IArgumentValue[]): CstType {
|
|
||||||
if (args.length === 0 || args.some(arg => !arg.value)) {
|
|
||||||
return templateType;
|
|
||||||
} else if (templateType === CstType.PREDICATE) {
|
|
||||||
return CstType.AXIOM;
|
|
||||||
} else {
|
|
||||||
return CstType.TERM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function substituteTemplateArgs(expression: string, args: IArgumentValue[]): string {
|
|
||||||
if (args.every(arg => !arg.value)) {
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
// TODO: figure out actual substitution
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadRSFormData(schema: IRSFormData): IRSForm {
|
|
||||||
const result = schema as IRSForm
|
|
||||||
result.graph = new Graph;
|
|
||||||
if (!result.items) {
|
|
||||||
result.stats = {
|
|
||||||
count_all: 0,
|
|
||||||
count_errors: 0,
|
|
||||||
count_property: 0,
|
|
||||||
count_incalc: 0,
|
|
||||||
|
|
||||||
count_termin: 0,
|
|
||||||
count_definition: 0,
|
|
||||||
count_convention: 0,
|
|
||||||
|
|
||||||
count_base: 0,
|
|
||||||
count_constant: 0,
|
|
||||||
count_structured: 0,
|
|
||||||
count_axiom: 0,
|
|
||||||
count_term: 0,
|
|
||||||
count_function: 0,
|
|
||||||
count_predicate: 0,
|
|
||||||
count_theorem: 0
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.stats = {
|
|
||||||
count_all: result.items.length || 0,
|
|
||||||
count_errors: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.parse?.status === ParsingStatus.INCORRECT ? 1 : 0) || 0, 0),
|
|
||||||
count_property: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.parse?.valueClass === ValueClass.PROPERTY ? 1 : 0) || 0, 0),
|
|
||||||
count_incalc: result.items.reduce(
|
|
||||||
(sum, cst) => sum +
|
|
||||||
((cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.INVALID) ? 1 : 0) || 0, 0),
|
|
||||||
|
|
||||||
count_termin: result.items.reduce(
|
|
||||||
(sum, cst) => (sum + (cst.term_raw ? 1 : 0) || 0), 0),
|
|
||||||
count_definition: result.items.reduce(
|
|
||||||
(sum, cst) => (sum + (cst.definition_raw ? 1 : 0) || 0), 0),
|
|
||||||
count_convention: result.items.reduce(
|
|
||||||
(sum, cst) => (sum + (cst.convention ? 1 : 0) || 0), 0),
|
|
||||||
|
|
||||||
count_base: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.BASE ? 1 : 0), 0),
|
|
||||||
count_constant: result.items?.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.CONSTANT ? 1 : 0), 0),
|
|
||||||
count_structured: result.items?.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.STRUCTURED ? 1 : 0), 0),
|
|
||||||
count_axiom: result.items?.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.AXIOM ? 1 : 0), 0),
|
|
||||||
count_term: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.TERM ? 1 : 0), 0),
|
|
||||||
count_function: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.FUNCTION ? 1 : 0), 0),
|
|
||||||
count_predicate: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.PREDICATE ? 1 : 0), 0),
|
|
||||||
count_theorem: result.items.reduce(
|
|
||||||
(sum, cst) => sum + (cst.cst_type === CstType.THEOREM ? 1 : 0), 0)
|
|
||||||
}
|
|
||||||
result.items.forEach(cst => {
|
|
||||||
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
|
||||||
cst.is_template = inferTemplate(cst.definition_formal);
|
|
||||||
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
|
||||||
result.graph.addNode(cst.id);
|
|
||||||
const dependencies = extractGlobals(cst.definition_formal);
|
|
||||||
dependencies.forEach(value => {
|
|
||||||
const source = schema.items.find(cst => cst.alias === value)
|
|
||||||
if (source) {
|
|
||||||
result.graph.addEdge(source.id, cst.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function matchConstituenta(target: IConstituenta, query: string, mode: CstMatchMode): boolean {
|
|
||||||
const matcher = new TextMatcher(query);
|
|
||||||
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
|
|
||||||
matcher.test(target.alias)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TERM) &&
|
|
||||||
matcher.test(target.term_resolved)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.EXPR) &&
|
|
||||||
matcher.test(target.definition_formal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TEXT)) {
|
|
||||||
return (matcher.test(target.definition_resolved) || matcher.test(target.convention));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inferStatus(parse?: ParsingStatus, value?: ValueClass): ExpressionStatus {
|
|
||||||
if (!parse || !value) {
|
|
||||||
return ExpressionStatus.UNDEFINED;
|
|
||||||
}
|
|
||||||
if (parse === ParsingStatus.UNDEF) {
|
|
||||||
return ExpressionStatus.UNKNOWN;
|
|
||||||
}
|
|
||||||
if (parse === ParsingStatus.INCORRECT) {
|
|
||||||
return ExpressionStatus.INCORRECT;
|
|
||||||
}
|
|
||||||
if (value === ValueClass.INVALID) {
|
|
||||||
return ExpressionStatus.INCALCULABLE;
|
|
||||||
}
|
|
||||||
if (value === ValueClass.PROPERTY) {
|
|
||||||
return ExpressionStatus.PROPERTY;
|
|
||||||
}
|
|
||||||
return ExpressionStatus.VERIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inferTemplate(expression: string): boolean {
|
|
||||||
const match = expression.match(/R\d+/g);
|
|
||||||
return (match && match?.length > 0) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inferClass(type: CstType, isTemplate: boolean): CstClass {
|
|
||||||
if (isTemplate) {
|
|
||||||
return CstClass.TEMPLATE;
|
|
||||||
}
|
|
||||||
switch (type) {
|
|
||||||
case CstType.BASE: return CstClass.BASIC;
|
|
||||||
case CstType.CONSTANT: return CstClass.BASIC;
|
|
||||||
case CstType.STRUCTURED: return CstClass.BASIC;
|
|
||||||
case CstType.TERM: return CstClass.DERIVED;
|
|
||||||
case CstType.FUNCTION: return CstClass.DERIVED;
|
|
||||||
case CstType.AXIOM: return CstClass.STATEMENT;
|
|
||||||
case CstType.PREDICATE: return CstClass.DERIVED;
|
|
||||||
case CstType.THEOREM: return CstClass.STATEMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isMockCst(cst: IConstituenta) {
|
|
||||||
return cst.id <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createMockConstituenta(schema: number, id: number, alias: string, type: CstType, comment: string): IConstituenta {
|
|
||||||
return {
|
|
||||||
id: id,
|
|
||||||
order: -1,
|
|
||||||
schema: schema,
|
|
||||||
alias: alias,
|
|
||||||
convention: comment,
|
|
||||||
cst_type: type,
|
|
||||||
term_raw: '',
|
|
||||||
term_resolved: '',
|
|
||||||
term_forms: [],
|
|
||||||
definition_formal: '',
|
|
||||||
definition_raw: '',
|
|
||||||
definition_resolved: '',
|
|
||||||
status: ExpressionStatus.INCORRECT,
|
|
||||||
is_template: false,
|
|
||||||
cst_class: CstClass.DERIVED,
|
|
||||||
parse: {
|
|
||||||
status: ParsingStatus.INCORRECT,
|
|
||||||
valueClass: ValueClass.INVALID,
|
|
||||||
typification: 'N/A',
|
|
||||||
syntaxTree: '',
|
|
||||||
args: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function applyFilterCategory(target: IConstituenta, schema: IRSFormData): IConstituenta[] {
|
|
||||||
const nextCategory = schema.items.find(
|
|
||||||
cst => (
|
|
||||||
cst.order > target.order &&
|
|
||||||
cst.cst_type === CATEGORY_CST_TYPE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return schema.items.filter(
|
|
||||||
cst => (
|
|
||||||
cst.order > target.order &&
|
|
||||||
(!nextCategory || cst.order <= nextCategory.order)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
192
rsconcept/frontend/src/models/rsformAPI.ts
Normal file
192
rsconcept/frontend/src/models/rsformAPI.ts
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
// ========== RSForm API =================
|
||||||
|
import { Graph } from '../utils/Graph';
|
||||||
|
import { TextMatcher } from '../utils/utils';
|
||||||
|
import { CstMatchMode } from './miscelanious';
|
||||||
|
import {
|
||||||
|
CATEGORY_CST_TYPE, CstClass, CstType,
|
||||||
|
ExpressionStatus, IConstituenta, IRSForm, IRSFormData
|
||||||
|
} from './rsform';
|
||||||
|
import { ParsingStatus, ValueClass } from './rslang';
|
||||||
|
import { extractGlobals } from './rslangAPI';
|
||||||
|
|
||||||
|
export function loadRSFormData(schema: IRSFormData): IRSForm {
|
||||||
|
const result = schema as IRSForm
|
||||||
|
result.graph = new Graph;
|
||||||
|
if (!result.items) {
|
||||||
|
result.stats = {
|
||||||
|
count_all: 0,
|
||||||
|
count_errors: 0,
|
||||||
|
count_property: 0,
|
||||||
|
count_incalc: 0,
|
||||||
|
|
||||||
|
count_termin: 0,
|
||||||
|
count_definition: 0,
|
||||||
|
count_convention: 0,
|
||||||
|
|
||||||
|
count_base: 0,
|
||||||
|
count_constant: 0,
|
||||||
|
count_structured: 0,
|
||||||
|
count_axiom: 0,
|
||||||
|
count_term: 0,
|
||||||
|
count_function: 0,
|
||||||
|
count_predicate: 0,
|
||||||
|
count_theorem: 0
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.stats = {
|
||||||
|
count_all: result.items.length || 0,
|
||||||
|
count_errors: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.parse?.status === ParsingStatus.INCORRECT ? 1 : 0) || 0, 0),
|
||||||
|
count_property: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.parse?.valueClass === ValueClass.PROPERTY ? 1 : 0) || 0, 0),
|
||||||
|
count_incalc: result.items.reduce(
|
||||||
|
(sum, cst) => sum +
|
||||||
|
((cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.INVALID) ? 1 : 0) || 0, 0),
|
||||||
|
|
||||||
|
count_termin: result.items.reduce(
|
||||||
|
(sum, cst) => (sum + (cst.term_raw ? 1 : 0) || 0), 0),
|
||||||
|
count_definition: result.items.reduce(
|
||||||
|
(sum, cst) => (sum + (cst.definition_raw ? 1 : 0) || 0), 0),
|
||||||
|
count_convention: result.items.reduce(
|
||||||
|
(sum, cst) => (sum + (cst.convention ? 1 : 0) || 0), 0),
|
||||||
|
|
||||||
|
count_base: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.BASE ? 1 : 0), 0),
|
||||||
|
count_constant: result.items?.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.CONSTANT ? 1 : 0), 0),
|
||||||
|
count_structured: result.items?.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.STRUCTURED ? 1 : 0), 0),
|
||||||
|
count_axiom: result.items?.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.AXIOM ? 1 : 0), 0),
|
||||||
|
count_term: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.TERM ? 1 : 0), 0),
|
||||||
|
count_function: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.FUNCTION ? 1 : 0), 0),
|
||||||
|
count_predicate: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.PREDICATE ? 1 : 0), 0),
|
||||||
|
count_theorem: result.items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.cst_type === CstType.THEOREM ? 1 : 0), 0)
|
||||||
|
}
|
||||||
|
result.items.forEach(cst => {
|
||||||
|
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
||||||
|
cst.is_template = inferTemplate(cst.definition_formal);
|
||||||
|
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
||||||
|
result.graph.addNode(cst.id);
|
||||||
|
const dependencies = extractGlobals(cst.definition_formal);
|
||||||
|
dependencies.forEach(value => {
|
||||||
|
const source = schema.items.find(cst => cst.alias === value)
|
||||||
|
if (source) {
|
||||||
|
result.graph.addEdge(source.id, cst.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function matchConstituenta(target: IConstituenta, query: string, mode: CstMatchMode): boolean {
|
||||||
|
const matcher = new TextMatcher(query);
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
|
||||||
|
matcher.test(target.alias)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TERM) &&
|
||||||
|
matcher.test(target.term_resolved)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.EXPR) &&
|
||||||
|
matcher.test(target.definition_formal)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TEXT)) {
|
||||||
|
return (matcher.test(target.definition_resolved) || matcher.test(target.convention));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferStatus(parse?: ParsingStatus, value?: ValueClass): ExpressionStatus {
|
||||||
|
if (!parse || !value) {
|
||||||
|
return ExpressionStatus.UNDEFINED;
|
||||||
|
}
|
||||||
|
if (parse === ParsingStatus.UNDEF) {
|
||||||
|
return ExpressionStatus.UNKNOWN;
|
||||||
|
}
|
||||||
|
if (parse === ParsingStatus.INCORRECT) {
|
||||||
|
return ExpressionStatus.INCORRECT;
|
||||||
|
}
|
||||||
|
if (value === ValueClass.INVALID) {
|
||||||
|
return ExpressionStatus.INCALCULABLE;
|
||||||
|
}
|
||||||
|
if (value === ValueClass.PROPERTY) {
|
||||||
|
return ExpressionStatus.PROPERTY;
|
||||||
|
}
|
||||||
|
return ExpressionStatus.VERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferTemplate(expression: string): boolean {
|
||||||
|
const match = expression.match(/R\d+/g);
|
||||||
|
return (match && match?.length > 0) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferClass(type: CstType, isTemplate: boolean): CstClass {
|
||||||
|
if (isTemplate) {
|
||||||
|
return CstClass.TEMPLATE;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case CstType.BASE: return CstClass.BASIC;
|
||||||
|
case CstType.CONSTANT: return CstClass.BASIC;
|
||||||
|
case CstType.STRUCTURED: return CstClass.BASIC;
|
||||||
|
case CstType.TERM: return CstClass.DERIVED;
|
||||||
|
case CstType.FUNCTION: return CstClass.DERIVED;
|
||||||
|
case CstType.AXIOM: return CstClass.STATEMENT;
|
||||||
|
case CstType.PREDICATE: return CstClass.DERIVED;
|
||||||
|
case CstType.THEOREM: return CstClass.STATEMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isMockCst(cst: IConstituenta) {
|
||||||
|
return cst.id <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMockConstituenta(schema: number, id: number, alias: string, type: CstType, comment: string): IConstituenta {
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
order: -1,
|
||||||
|
schema: schema,
|
||||||
|
alias: alias,
|
||||||
|
convention: comment,
|
||||||
|
cst_type: type,
|
||||||
|
term_raw: '',
|
||||||
|
term_resolved: '',
|
||||||
|
term_forms: [],
|
||||||
|
definition_formal: '',
|
||||||
|
definition_raw: '',
|
||||||
|
definition_resolved: '',
|
||||||
|
status: ExpressionStatus.INCORRECT,
|
||||||
|
is_template: false,
|
||||||
|
cst_class: CstClass.DERIVED,
|
||||||
|
parse: {
|
||||||
|
status: ParsingStatus.INCORRECT,
|
||||||
|
valueClass: ValueClass.INVALID,
|
||||||
|
typification: 'N/A',
|
||||||
|
syntaxTree: '',
|
||||||
|
args: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyFilterCategory(target: IConstituenta, schema: IRSFormData): IConstituenta[] {
|
||||||
|
const nextCategory = schema.items.find(
|
||||||
|
cst => (
|
||||||
|
cst.order > target.order &&
|
||||||
|
cst.cst_type === CATEGORY_CST_TYPE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return schema.items.filter(
|
||||||
|
cst => (
|
||||||
|
cst.order > target.order &&
|
||||||
|
(!nextCategory || cst.order <= nextCategory.order)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -247,4 +247,4 @@ export function resolveErrorClass(error: RSErrorType): RSErrorClass {
|
||||||
} else {
|
} else {
|
||||||
return RSErrorClass.UNKNOWN;
|
return RSErrorClass.UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
91
rsconcept/frontend/src/models/rslangAPI.ts
Normal file
91
rsconcept/frontend/src/models/rslangAPI.ts
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// Module: RSLang model API
|
||||||
|
|
||||||
|
import { CstType } from './rsform';
|
||||||
|
import { IArgumentValue } from './rslang'
|
||||||
|
|
||||||
|
export function extractGlobals(expression: string): Set<string> {
|
||||||
|
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inferTemplatedType(templateType: CstType, args: IArgumentValue[]): CstType {
|
||||||
|
if (args.length === 0 || args.some(arg => !arg.value)) {
|
||||||
|
return templateType;
|
||||||
|
} else if (templateType === CstType.PREDICATE) {
|
||||||
|
return CstType.AXIOM;
|
||||||
|
} else {
|
||||||
|
return CstType.TERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function substituteTemplateArgs(expression: string, args: IArgumentValue[]): string {
|
||||||
|
if (args.every(arg => !arg.value)) {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapping: { [key: string]: string } = {};
|
||||||
|
args.filter(arg => !!arg.value).forEach(arg => { mapping[arg.alias] = arg.value!; })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: figure out actual substitution
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
export function splitTemplateDefinition(target: string) {
|
||||||
|
let start = 0;
|
||||||
|
for (; start < target.length && target[start] !== '['; ++start) ;
|
||||||
|
if (start < target.length) {
|
||||||
|
for (let counter = 0, end = start + 1; end < target.length; ++end) {
|
||||||
|
if (target[end] === '[') {
|
||||||
|
++counter;
|
||||||
|
} else if (target[end] === ']') {
|
||||||
|
if (counter !== 0) {
|
||||||
|
--counter;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
head: '',
|
||||||
|
body: target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function applyPattern(text: string, mapping: { [key: string]: string }, pattern: RegExp): string {
|
||||||
|
// /** Apply mapping to matching in regular expression patter subgroup 1. */
|
||||||
|
// if (text === '' || pattern === null) {
|
||||||
|
// return text;
|
||||||
|
// }
|
||||||
|
// let posInput: number = 0;
|
||||||
|
// let output: string = '';
|
||||||
|
// const patternMatches = text.matchAll(pattern);
|
||||||
|
// for (const segment of patternMatches) {
|
||||||
|
// const entity = segment[1];
|
||||||
|
// if (entity in mapping) {
|
||||||
|
// output += text.substring(posInput, segment.index);
|
||||||
|
// output += mapping[entity];
|
||||||
|
// output += text.substring(segment.index, segment.index + segment[0].length);
|
||||||
|
// posInput = segment.index + segment[0].length;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// output += text.substring(posInput);
|
||||||
|
// return output;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// def apply_pattern(text: str, mapping: dict[str, str], pattern: re.Pattern[str]) -> str:
|
||||||
|
// ''' Apply mapping to matching in regular expression patter subgroup 1. '''
|
||||||
|
// if text == '' or pattern == '':
|
||||||
|
// return text
|
||||||
|
// pos_input: int = 0
|
||||||
|
// output: str = ''
|
||||||
|
// for segment in re.finditer(pattern, text):
|
||||||
|
// entity = segment.group(1)
|
||||||
|
// if entity in mapping:
|
||||||
|
// output += text[pos_input : segment.start(1)]
|
||||||
|
// output += mapping[entity]
|
||||||
|
// output += text[segment.end(1) : segment.end(0)]
|
||||||
|
// pos_input = segment.end(0)
|
||||||
|
// output += text[pos_input : len(text)]
|
||||||
|
// return output
|
|
@ -2,7 +2,8 @@ import { useMemo } from 'react';
|
||||||
|
|
||||||
import { useConceptTheme } from '../../../context/ThemeContext';
|
import { useConceptTheme } from '../../../context/ThemeContext';
|
||||||
import { ExpressionStatus } from '../../../models/rsform';
|
import { ExpressionStatus } from '../../../models/rsform';
|
||||||
import { type IConstituenta, inferStatus } from '../../../models/rsform';
|
import { type IConstituenta } from '../../../models/rsform';
|
||||||
|
import { inferStatus } from '../../../models/rsformAPI';
|
||||||
import { IExpressionParse, ParsingStatus } from '../../../models/rslang';
|
import { IExpressionParse, ParsingStatus } from '../../../models/rslang';
|
||||||
import { colorbgCstStatus } from '../../../utils/color';
|
import { colorbgCstStatus } from '../../../utils/color';
|
||||||
import { describeExpressionStatus, labelExpressionStatus } from '../../../utils/labels';
|
import { describeExpressionStatus, labelExpressionStatus } from '../../../utils/labels';
|
||||||
|
|
|
@ -14,8 +14,9 @@ import useWindowSize from '../../../hooks/useWindowSize';
|
||||||
import { DependencyMode as CstSource } from '../../../models/miscelanious';
|
import { DependencyMode as CstSource } from '../../../models/miscelanious';
|
||||||
import { CstMatchMode } from '../../../models/miscelanious';
|
import { CstMatchMode } from '../../../models/miscelanious';
|
||||||
import { applyGraphFilter } from '../../../models/miscelanious';
|
import { applyGraphFilter } from '../../../models/miscelanious';
|
||||||
import { CstType, extractGlobals, IConstituenta, isMockCst, matchConstituenta } from '../../../models/rsform';
|
import { CstType, IConstituenta } from '../../../models/rsform';
|
||||||
import { createMockConstituenta } from '../../../models/rsform';
|
import { createMockConstituenta, isMockCst, matchConstituenta } from '../../../models/rsformAPI';
|
||||||
|
import { extractGlobals } from '../../../models/rslangAPI';
|
||||||
import { prefixes } from '../../../utils/constants';
|
import { prefixes } from '../../../utils/constants';
|
||||||
import {
|
import {
|
||||||
describeConstituenta, describeCstMathchMode,
|
describeConstituenta, describeCstMathchMode,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user