ConceptPortal-public/rsconcept/frontend/src/utils/models.ts

429 lines
11 KiB
TypeScript
Raw Normal View History

2023-07-29 03:31:21 +03:00
import { RSErrorType, TokenID } from './enums'
2023-07-29 21:23:18 +03:00
import { Graph } from './Graph'
2023-07-29 03:31:21 +03:00
// ========= Users ===========
export interface IUser {
id: number | null
2023-07-25 20:27:29 +03:00
username: string
is_staff: boolean
email: string
first_name: string
last_name: string
2023-07-20 17:11:03 +03:00
}
export interface ICurrentUser extends Pick<IUser, 'id' | 'username' | 'is_staff'> {}
2023-07-20 17:11:03 +03:00
export interface IUserLoginData extends Pick<IUser, 'username'> {
2023-07-25 20:27:29 +03:00
password: string
2023-07-20 17:11:03 +03:00
}
export interface IUserSignupData extends Omit<IUser, 'is_staff' | 'id'> {
password: string
password2: string
2023-07-20 17:11:03 +03:00
}
2023-07-31 21:45:27 +03:00
export interface IUserUpdateData extends Omit<IUser, 'is_staff' | 'id'> {}
export interface IUserProfile extends Omit<IUser, 'is_staff'> {}
export interface IUserInfo extends Omit<IUserProfile, 'email'> {}
2023-07-20 17:11:03 +03:00
2023-08-10 13:53:19 +03:00
export interface IUserUpdatePassword {
old_password: string
new_password: string
}
2023-07-29 03:31:21 +03:00
// ======== RS Parsing ============
2023-07-20 17:11:03 +03:00
export enum Syntax {
2023-07-25 20:27:29 +03:00
UNDEF = 'undefined',
ASCII = 'ascii',
MATH = 'math'
2023-07-20 17:11:03 +03:00
}
2023-07-29 03:31:21 +03:00
export enum ValueClass {
INVALID = 'invalid',
VALUE = 'value',
PROPERTY = 'property'
}
2023-07-20 17:11:03 +03:00
export enum ParsingStatus {
2023-07-25 20:27:29 +03:00
UNDEF = 'undefined',
VERIFIED = 'verified',
INCORRECT = 'incorrect'
2023-07-20 17:11:03 +03:00
}
2023-07-29 03:31:21 +03:00
export interface IRSErrorDescription {
errorType: RSErrorType
position: number
isCritical: boolean
params: string[]
}
2023-07-29 03:31:21 +03:00
export interface ISyntaxTreeNode {
uid: number
parent: number
typeID: TokenID
start: number
finish: number
2023-08-01 21:55:18 +03:00
data: {
dataType: string,
value: unknown
}
2023-07-29 03:31:21 +03:00
}
export type SyntaxTree = ISyntaxTreeNode[]
export interface IFunctionArg {
alias: string
typification: string
}
2023-07-29 03:31:21 +03:00
export interface IExpressionParse {
parseResult: boolean
syntax: Syntax
typification: string
valueClass: ValueClass
2023-07-29 03:31:21 +03:00
errors: IRSErrorDescription[]
astText: string
2023-07-29 03:31:21 +03:00
ast: SyntaxTree
args: IFunctionArg[]
}
2023-07-29 03:31:21 +03:00
export interface IRSExpression {
expression: string
}
// ====== Constituenta ==========
export enum CstType {
BASE = 'basic',
STRUCTURED = 'structure',
TERM = 'term',
AXIOM = 'axiom',
FUNCTION = 'function',
PREDICATE = 'predicate',
CONSTANT = 'constant',
THEOREM = 'theorem'
}
2023-08-16 00:39:16 +03:00
export enum CstClass {
BASIC = 'basic',
DERIVED = 'derived',
STATEMENT = 'statement',
TEMPLATE = 'template'
}
2023-07-20 17:11:03 +03:00
export interface IConstituenta {
2023-07-25 20:27:29 +03:00
id: number
alias: string
cstType: CstType
convention: string
term: {
2023-07-25 20:27:29 +03:00
raw: string
resolved: string
forms: string[]
2023-07-25 20:27:29 +03:00
}
definition: {
2023-07-25 20:27:29 +03:00
formal: string
text: {
raw: string
resolved: string
2023-07-20 17:11:03 +03:00
}
2023-07-25 20:27:29 +03:00
}
2023-08-16 00:39:16 +03:00
cstClass: CstClass
status: ExpressionStatus
2023-08-16 00:39:16 +03:00
isTemplate: boolean
parse: {
2023-07-25 20:27:29 +03:00
status: ParsingStatus
valueClass: ValueClass
typification: string
syntaxTree: string
args: IFunctionArg[]
2023-07-25 20:27:29 +03:00
}
2023-07-20 17:11:03 +03:00
}
export interface IConstituentaMeta {
id: number
schema: number
order: number
alias: string
convention: string
cst_type: CstType
definition_formal: string
definition_raw: string
definition_resolved: string
term_raw: string
term_resolved: string
}
export interface IConstituentaID extends Pick<IConstituentaMeta, 'id'>{}
export interface IConstituentaList {
items: IConstituentaID[]
}
export interface ICstCreateData extends Pick<IConstituentaMeta, 'alias' | 'cst_type'> {
insert_after: number | null
}
export interface ICstMovetoData extends IConstituentaList {
move_to: number
}
export interface ICstUpdateData
extends Pick<IConstituentaMeta, 'id' | 'alias' | 'convention' | 'definition_formal' | 'definition_raw' | 'term_raw'> {}
export interface ICstCreatedResponse {
new_cst: IConstituentaMeta
schema: IRSFormData
}
// ========== RSForm ============
2023-07-20 17:11:03 +03:00
export interface IRSFormStats {
2023-07-25 20:27:29 +03:00
count_all: number
count_errors: number
count_property: number
count_incalc: number
count_termin: number
count_base: number
count_constant: number
count_structured: number
count_axiom: number
count_term: number
count_function: number
count_predicate: number
count_theorem: number
2023-07-20 17:11:03 +03:00
}
export interface IRSForm {
2023-07-25 20:27:29 +03:00
id: number
title: string
alias: string
comment: string
is_common: boolean
time_create: string
time_update: string
owner: number | null
items: IConstituenta[]
stats: IRSFormStats
2023-07-29 21:23:18 +03:00
graph: Graph
2023-07-20 17:11:03 +03:00
}
2023-07-30 00:47:07 +03:00
export interface IRSFormData extends Omit<IRSForm, 'stats' | 'graph'> {}
export interface IRSFormMeta extends Omit<IRSForm, 'items' | 'stats' | 'graph'> {}
export interface IRSFormUpdateData
extends Omit<IRSFormMeta, 'time_create' | 'time_update' | 'id' | 'owner'> {}
export interface IRSFormCreateData
extends IRSFormUpdateData {
2023-07-25 20:27:29 +03:00
file?: File
fileName?: string
2023-07-20 17:11:03 +03:00
}
2023-07-27 22:04:25 +03:00
export interface IRSFormUploadData {
load_metadata: boolean
file: File
fileName: string
}
2023-08-01 20:14:03 +03:00
// ========== Library =====
export interface ILibraryFilter {
ownedBy?: number
is_common?: boolean
queryMeta?: string
}
// ================ Misc types ================
2023-07-20 17:11:03 +03:00
// Constituenta edit mode
export enum EditMode {
2023-07-25 20:27:29 +03:00
TEXT = 'text',
RSLANG = 'rslang'
2023-07-20 17:11:03 +03:00
}
// RSExpression status
export enum ExpressionStatus {
2023-08-16 00:39:16 +03:00
UNDEFINED = 'undefined',
UNKNOWN = 'unknown',
INCORRECT = 'incorrect',
INCALCULABLE = 'incalculable',
PROPERTY = 'property',
VERIFIED = 'verified'
2023-07-20 17:11:03 +03:00
}
// Dependency mode for schema analysis
export enum DependencyMode {
ALL = 0,
EXPRESSION,
OUTPUTS,
INPUTS,
EXPAND_OUTPUTS,
EXPAND_INPUTS
}
// Constituent compare mode
export enum CstMatchMode {
ALL = 1,
EXPR,
TERM,
TEXT,
NAME
}
2023-07-29 21:23:18 +03:00
// ========== Model functions =================
2023-07-20 17:11:03 +03:00
export function inferStatus(parse?: ParsingStatus, value?: ValueClass): ExpressionStatus {
2023-07-25 20:27:29 +03:00
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;
}
2023-08-16 00:39:16 +03:00
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;
}
2023-07-20 17:11:03 +03:00
}
export function extractGlobals(expression: string): Set<string> {
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
}
export function LoadRSFormData(schema: IRSFormData): IRSForm {
const result = schema as IRSForm
2023-07-29 21:23:18 +03:00
result.graph = new Graph;
if (!result.items) {
result.stats = {
2023-07-25 20:27:29 +03:00
count_all: 0,
count_errors: 0,
count_property: 0,
count_incalc: 0,
count_termin: 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
2023-07-20 17:11:03 +03:00
}
return result;
2023-07-25 20:27:29 +03:00
}
result.stats = {
2023-07-29 21:23:18 +03:00
count_all: result.items.length || 0,
count_errors: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.parse?.status === ParsingStatus.INCORRECT ? 1 : 0) || 0, 0),
2023-07-29 21:23:18 +03:00
count_property: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.parse?.valueClass === ValueClass.PROPERTY ? 1 : 0) || 0, 0),
2023-07-29 21:23:18 +03:00
count_incalc: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum +
((cst.parse?.status === ParsingStatus.VERIFIED && cst.parse?.valueClass === ValueClass.INVALID) ? 1 : 0) || 0, 0),
2023-07-29 21:23:18 +03:00
count_termin: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => (sum + (cst.term?.raw ? 1 : 0) || 0), 0),
2023-07-29 21:23:18 +03:00
count_base: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.BASE ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_constant: result.items?.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.CONSTANT ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_structured: result.items?.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.STRUCTURED ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_axiom: result.items?.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.AXIOM ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_term: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.TERM ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_function: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.FUNCTION ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_predicate: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.PREDICATE ? 1 : 0), 0),
2023-07-29 21:23:18 +03:00
count_theorem: result.items.reduce(
2023-07-25 20:27:29 +03:00
(sum, cst) => sum + (cst.cstType === CstType.THEOREM ? 1 : 0), 0)
}
2023-07-29 21:23:18 +03:00
result.items.forEach(cst => {
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
2023-08-16 00:39:16 +03:00
cst.isTemplate = inferTemplate(cst.definition.formal);
cst.cstClass = inferClass(cst.cstType, cst.isTemplate);
2023-07-29 21:23:18 +03:00
result.graph.addNode(cst.id);
const dependencies = extractGlobals(cst.definition.formal);
dependencies.forEach(value => {
2023-07-29 23:00:03 +03:00
const source = schema.items.find(cst => cst.alias === value)
if (source) {
result.graph.addEdge(source.id, cst.id);
2023-07-29 21:23:18 +03:00
}
});
});
return result;
2023-07-20 17:11:03 +03:00
}
export function matchConstituenta(query: string, target: IConstituenta, mode: CstMatchMode) {
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
target.alias.match(query)) {
2023-07-25 20:27:29 +03:00
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TERM) &&
target.term.resolved.match(query)) {
2023-07-25 20:27:29 +03:00
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.EXPR) &&
target.definition.formal.match(query)) {
2023-08-01 20:14:03 +03:00
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TEXT)) {
return (target.definition.text.resolved.match(query) || target.convention.match(query));
}
return false;
2023-08-01 20:14:03 +03:00
}
export function matchRSFormMeta(query: string, target: IRSFormMeta) {
const queryI = query.toUpperCase();
if (target.alias.toUpperCase().match(queryI)) {
2023-07-25 20:27:29 +03:00
return true;
2023-08-01 20:14:03 +03:00
} else if (target.title.toUpperCase().match(queryI)) {
2023-07-25 20:27:29 +03:00
return true;
} else {
return false;
}
}
export function applyGraphFilter(schema: IRSForm, start: number, mode: DependencyMode): IConstituenta[] {
if (mode === DependencyMode.ALL) {
return schema.items;
}
let ids: number[] | undefined = undefined
switch (mode) {
case DependencyMode.OUTPUTS: { ids = schema.graph.nodes.get(start)?.outputs; break; }
case DependencyMode.INPUTS: { ids = schema.graph.nodes.get(start)?.inputs; break; }
case DependencyMode.EXPAND_OUTPUTS: { ids = schema.graph.expandOutputs([start]) ; break; }
case DependencyMode.EXPAND_INPUTS: { ids = schema.graph.expandInputs([start]) ; break; }
}
if (!ids) {
return schema.items;
} else {
return schema.items.filter(cst => ids!.find(id => id === cst.id));
}
}