Portal/rsconcept/frontend/src/features/oss/backend/oss-loader.ts

95 lines
3.1 KiB
TypeScript
Raw Normal View History

2024-06-07 20:17:03 +03:00
/**
* Module: OSS data loading and processing.
*/
2025-02-26 00:16:22 +03:00
import { type ILibraryItem } from '@/features/library';
2025-02-12 21:36:03 +03:00
2025-03-12 11:54:32 +03:00
import { Graph } from '@/models/graph1';
2025-02-20 20:22:05 +03:00
import { type IOperation, type IOperationSchema, type IOperationSchemaStats } from '../models/oss';
2025-02-12 21:36:03 +03:00
2025-02-20 20:22:05 +03:00
import { type IOperationSchemaDTO, OperationType } from './types';
2024-06-07 20:17:03 +03:00
/**
* Loads data into an {@link IOperationSchema} based on {@link IOperationSchemaDTO}.
2024-06-07 20:17:03 +03:00
*
*/
export class OssLoader {
private oss: IOperationSchema;
2024-07-20 18:26:32 +03:00
private graph: Graph = new Graph();
private operationByID = new Map<number, IOperation>();
2025-02-12 15:12:59 +03:00
private schemaIDs: number[] = [];
private items: ILibraryItem[];
2024-06-07 20:17:03 +03:00
constructor(input: IOperationSchemaDTO, items: ILibraryItem[]) {
this.oss = input as unknown as IOperationSchema;
this.items = items;
2024-06-07 20:17:03 +03:00
}
produceOSS(): IOperationSchema {
const result = this.oss;
2024-07-20 18:26:32 +03:00
this.prepareLookups();
this.createGraph();
2024-07-26 00:33:22 +03:00
this.extractSchemas();
this.inferOperationAttributes();
2024-07-20 18:26:32 +03:00
result.operationByID = this.operationByID;
result.graph = this.graph;
result.schemas = this.schemaIDs;
2024-07-26 00:33:22 +03:00
result.stats = this.calculateStats();
2024-06-07 20:17:03 +03:00
return result;
}
2024-07-20 18:26:32 +03:00
private prepareLookups() {
this.oss.items.forEach(operation => {
this.operationByID.set(operation.id, operation);
2024-07-20 18:26:32 +03:00
this.graph.addNode(operation.id);
});
}
private createGraph() {
this.oss.arguments.forEach(argument => this.graph.addEdge(argument.argument, argument.operation));
}
2024-07-26 00:33:22 +03:00
private extractSchemas() {
this.schemaIDs = this.oss.items.map(operation => operation.result).filter(item => item !== null);
2024-07-26 00:33:22 +03:00
}
private inferOperationAttributes() {
this.graph.topologicalOrder().forEach(operationID => {
const operation = this.operationByID.get(operationID)!;
const schema = this.items.find(item => item.id === operation.result);
2024-08-17 12:16:50 +03:00
operation.is_consolidation = this.inferConsolidation(operationID);
operation.is_owned = !schema || (schema.owner === this.oss.owner && schema.location === this.oss.location);
operation.substitutions = this.oss.substitutions.filter(item => item.operation === operationID);
operation.arguments = this.oss.arguments
.filter(item => item.operation === operationID)
.map(item => item.argument);
});
}
private inferConsolidation(operationID: number): boolean {
2024-08-17 12:16:50 +03:00
const inputs = this.graph.expandInputs([operationID]);
if (inputs.length === 0) {
return false;
}
const ancestors = [...inputs];
inputs.forEach(input => {
ancestors.push(...this.graph.expandAllInputs([input]));
});
const unique = new Set(ancestors);
return unique.size < ancestors.length;
}
2024-07-26 00:33:22 +03:00
private calculateStats(): IOperationSchemaStats {
const items = this.oss.items;
return {
count_operations: items.length,
count_inputs: items.filter(item => item.operation_type === OperationType.INPUT).length,
count_synthesis: items.filter(item => item.operation_type === OperationType.SYNTHESIS).length,
2024-08-23 21:28:54 +03:00
count_schemas: this.schemaIDs.length,
count_owned: items.filter(item => !!item.result && item.is_owned).length
2024-07-26 00:33:22 +03:00
};
}
2024-06-07 20:17:03 +03:00
}