Merged PR 212: Optimize FindChildrenById from O(n) to O(1)

Optimize FindChildrenById from O(n) to O(1):
- Deprecate FindContainerByIdDFS
- Container: Replace Children to string[]
- Add HashMap to IHistoryState that contains all containers

To access a container by id now cost O(1) without any additional cost

+ Implement CICD for SVGLibs
This commit is contained in:
Eric Nguyen 2022-10-12 09:39:54 +00:00
parent 466ef2b08b
commit c256a76e01
45 changed files with 775 additions and 450 deletions

View file

@ -1,9 +1,22 @@
import { IContainerModel } from '../Interfaces/IContainerModel';
export function * MakeChildrenIterator(containers: Map<string, IContainerModel>, childrenIds: string[]): Generator<IContainerModel, void, unknown> {
for (const childId of childrenIds) {
const child = FindContainerById(containers, childId);
if (child === undefined) {
return;
}
yield child;
};
}
/**
* Returns a Generator iterating of over the children depth-first
*/
export function * MakeDFSIterator(root: IContainerModel, enableHideChildrenInTreeview = false): Generator<IContainerModel, void, unknown> {
export function * MakeDFSIterator(root: IContainerModel, containers: Map<string, IContainerModel>, enableHideChildrenInTreeview = false): Generator<IContainerModel, void, unknown> {
const queue: IContainerModel[] = [root];
const visited = new Set<IContainerModel>(queue);
while (queue.length > 0) {
@ -16,8 +29,9 @@ export function * MakeDFSIterator(root: IContainerModel, enableHideChildrenInTre
}
for (let i = container.children.length - 1; i >= 0; i--) {
const child = container.children[i];
if (visited.has(child)) {
const childId = container.children[i];
const child = FindContainerById(containers, childId);
if (child === undefined || visited.has(child)) {
continue;
}
visited.add(child);
@ -38,7 +52,7 @@ export interface ContainerAndDepthAndTransform extends ContainerAndDepth {
/**
* Returns a Generator iterating of over the children depth-first
*/
export function * MakeBFSIterator(root: IContainerModel): Generator<ContainerAndDepth, void, unknown> {
export function * MakeBFSIterator(root: IContainerModel, containers: Map<string, IContainerModel>): Generator<ContainerAndDepth, void, unknown> {
const queue: IContainerModel[] = [root];
let depth = 0;
while (queue.length > 0) {
@ -51,7 +65,13 @@ export function * MakeBFSIterator(root: IContainerModel): Generator<ContainerAnd
};
for (let i = container.children.length - 1; i >= 0; i--) {
const child = container.children[i];
const childId = container.children[i];
const child = FindContainerById(containers, childId);
if (child === undefined) {
continue;
}
queue.push(child);
}
}
@ -61,6 +81,7 @@ export function * MakeBFSIterator(root: IContainerModel): Generator<ContainerAnd
export function * MakeRecursionDFSIterator(
root: IContainerModel | null,
containers: Map<string, IContainerModel>,
depth: number,
currentTransform: [number, number],
enableHideChildrenInTreeview: boolean = false
@ -79,9 +100,16 @@ export function * MakeRecursionDFSIterator(
return;
}
for (const container of root.children) {
for (const containerId of root.children) {
const container = FindContainerById(containers, containerId);
if (container === undefined) {
continue;
}
yield * MakeRecursionDFSIterator(
container,
containers,
depth + 1,
[
currentTransform[0] + root.properties.x,
@ -185,8 +213,15 @@ export function ApplyParentTransform(
return [x, y];
}
export function FindContainerById(root: IContainerModel, id: string): IContainerModel | undefined {
const it = MakeDFSIterator(root);
/**
* Returns the container by id
* @deprecated Please use FindContainerById
* @param root Root of the container tree
* @param id Id of the container to find
* @returns The container found or undefined if not found
*/
export function FindContainerByIdDFS(root: IContainerModel, containers: Map<string, IContainerModel>, id: string): IContainerModel | undefined {
const it = MakeDFSIterator(root, containers);
for (const container of it) {
if (container.properties.id === id) {
return container;
@ -195,6 +230,17 @@ export function FindContainerById(root: IContainerModel, id: string): IContainer
return undefined;
}
/**
* Returns the container by id
* For now, does the same as containers.get(id)
* @param containers Map of containers
* @param id id of container
* @returns Container by id
*/
export function FindContainerById(containers: Map<string, IContainerModel>, id: string): IContainerModel | undefined {
return containers.get(id);
}
export interface IPair<T> {
cur: T
next: T