Refactor InitializeChildrenWithPattern
This commit is contained in:
parent
5acc57cf7f
commit
5bc47d02cb
1 changed files with 143 additions and 53 deletions
|
@ -10,7 +10,7 @@ import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { IPattern, GetPattern, ContainerOrPattern } from '../../../Interfaces/IPattern';
|
import { IPattern, GetPattern, ContainerOrPattern } from '../../../Interfaces/IPattern';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { GetDefaultContainerProps, DEFAULTCHILDTYPE_MAX_DEPTH, DEFAULTCHILDTYPE_ALLOW_CYCLIC } from '../../../utils/default';
|
import { GetDefaultContainerProps } from '../../../utils/default';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
import { ApplyMargin } from '../../../utils/svg';
|
import { ApplyMargin } from '../../../utils/svg';
|
||||||
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
||||||
|
@ -301,9 +301,10 @@ function InitializeChildrenWithPattern(
|
||||||
const configs: Map<string, IAvailableContainer> = new Map(configuration.AvailableContainers.map(config => [config.Type, config]));
|
const configs: Map<string, IAvailableContainer> = new Map(configuration.AvailableContainers.map(config => [config.Type, config]));
|
||||||
const patterns: Map<string, IPattern> = new Map(configuration.Patterns.map(pattern => [pattern.id, pattern]));
|
const patterns: Map<string, IPattern> = new Map(configuration.Patterns.map(pattern => [pattern.id, pattern]));
|
||||||
const containerOrPattern = GetPattern(patternId, configs, patterns);
|
const containerOrPattern = GetPattern(patternId, configs, patterns);
|
||||||
const pattern = containerOrPattern as IPattern;
|
const pattern = containerOrPattern as IPattern | IAvailableContainer;
|
||||||
|
|
||||||
if (pattern.children === undefined) {
|
if (!('children' in pattern)) {
|
||||||
|
// containerOrPattern is not a pattern but a container
|
||||||
const container = containerOrPattern as IAvailableContainer;
|
const container = containerOrPattern as IAvailableContainer;
|
||||||
// Add Container
|
// Add Container
|
||||||
AddNewContainerToParent(
|
AddNewContainerToParent(
|
||||||
|
@ -315,11 +316,38 @@ function InitializeChildrenWithPattern(
|
||||||
newCounters,
|
newCounters,
|
||||||
symbols
|
symbols
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BFS over patterns
|
// BFS over patterns
|
||||||
|
BuildPatterns(pattern, newContainer, configuration, containers, newCounters, symbols, configs, patterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the BFS algorithm to build containers from given patterns
|
||||||
|
* from the top to the bottom
|
||||||
|
*
|
||||||
|
* @param pattern
|
||||||
|
* @param newContainer
|
||||||
|
* @param configuration
|
||||||
|
* @param containers
|
||||||
|
* @param newCounters
|
||||||
|
* @param symbols
|
||||||
|
* @param configs
|
||||||
|
* @param patterns
|
||||||
|
*/
|
||||||
|
function BuildPatterns(
|
||||||
|
rootPattern: IPattern,
|
||||||
|
newContainer: ContainerModel,
|
||||||
|
configuration: IConfiguration,
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
|
newCounters: Record<string, number>,
|
||||||
|
symbols: Map<string, ISymbolModel>,
|
||||||
|
configs: Map<string, IAvailableContainer>,
|
||||||
|
patterns: Map<string, IPattern>
|
||||||
|
): void {
|
||||||
const rootNode: Node = {
|
const rootNode: Node = {
|
||||||
containerOrPattern: pattern,
|
containerOrPattern: rootPattern,
|
||||||
parent: newContainer
|
parent: newContainer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -330,11 +358,55 @@ function InitializeChildrenWithPattern(
|
||||||
while (levelSize-- !== 0) {
|
while (levelSize-- !== 0) {
|
||||||
const node = queue.shift() as Node;
|
const node = queue.shift() as Node;
|
||||||
|
|
||||||
const pattern = node.containerOrPattern as IPattern;
|
const newParent = AddContainerInLevel(node, maxLevelSize, levelSize, configuration, containers, newCounters, symbols, configs);
|
||||||
|
|
||||||
if (pattern.children === undefined) {
|
if (newParent === undefined) {
|
||||||
// Add Container
|
// node.pattern is not a IPattern, there is no children to iterate
|
||||||
const containerConfig = node.containerOrPattern as IAvailableContainer;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = newParent.pattern.children.length - 1; i >= 0; i--) {
|
||||||
|
const nextNode = GetNextNode(newParent.parent, newParent.pattern, i, configs, patterns);
|
||||||
|
|
||||||
|
if (nextNode === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.push(nextNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new container in the parent if node.pattern is a Pattern.
|
||||||
|
* Then, return the next parent to iterate with a pattern/container.
|
||||||
|
* Otherwise, if node.pattern is a IAvailableContainer,
|
||||||
|
* create the container from node.pattern and return undefined.
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
* @param maxLevelSize
|
||||||
|
* @param levelSize
|
||||||
|
* @param configuration
|
||||||
|
* @param containers
|
||||||
|
* @param newCounters
|
||||||
|
* @param symbols
|
||||||
|
* @param configs
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function AddContainerInLevel(
|
||||||
|
node: Node,
|
||||||
|
maxLevelSize: number,
|
||||||
|
levelSize: number,
|
||||||
|
configuration: IConfiguration,
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
|
newCounters: Record<string, number>,
|
||||||
|
symbols: Map<string, ISymbolModel>,
|
||||||
|
configs: Map<string, IAvailableContainer>
|
||||||
|
): { parent: IContainerModel, pattern: IPattern } | undefined {
|
||||||
|
if (!('children' in node.containerOrPattern)) {
|
||||||
|
// Add Container from pattern
|
||||||
|
const containerConfig: IAvailableContainer = node.containerOrPattern;
|
||||||
const index = maxLevelSize - levelSize;
|
const index = maxLevelSize - levelSize;
|
||||||
AddNewContainerToParent(
|
AddNewContainerToParent(
|
||||||
containerConfig,
|
containerConfig,
|
||||||
|
@ -345,17 +417,25 @@ function InitializeChildrenWithPattern(
|
||||||
newCounters,
|
newCounters,
|
||||||
symbols
|
symbols
|
||||||
);
|
);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent = node.parent;
|
const pattern: IPattern = node.containerOrPattern;
|
||||||
if (pattern.wrapper !== undefined) {
|
const parent = node.parent;
|
||||||
// Add Container
|
|
||||||
|
if (pattern.wrapper === undefined) {
|
||||||
|
return { parent, pattern };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Container from wrapper
|
||||||
|
// and set the new parent as the child of this parent
|
||||||
const container = configs.get(pattern.wrapper);
|
const container = configs.get(pattern.wrapper);
|
||||||
if (container === undefined) {
|
if (container === undefined) {
|
||||||
console.warn(`[InitializeChildrenFromPattern] IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
|
console.warn(`[InitializeChildrenFromPattern] IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
|
||||||
Process will ignore the container.`);
|
Process will ignore the container.`);
|
||||||
} else {
|
return { parent, pattern };
|
||||||
|
}
|
||||||
|
|
||||||
const newChildContainer = AddNewContainerToParent(
|
const newChildContainer = AddNewContainerToParent(
|
||||||
container,
|
container,
|
||||||
configuration,
|
configuration,
|
||||||
|
@ -368,29 +448,39 @@ function InitializeChildrenWithPattern(
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
// iterate
|
// change the parent to be the child of the wrapper
|
||||||
parent = newChildContainer;
|
return { parent: newChildContainer, pattern };
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = pattern.children.length - 1; i >= 0; i--) {
|
/**
|
||||||
|
* Return the next node from the given pattern from the configs
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* @param pattern
|
||||||
|
* @param i
|
||||||
|
* @param configs
|
||||||
|
* @param patterns
|
||||||
|
* @returns {Node} The next node
|
||||||
|
*/
|
||||||
|
function GetNextNode(
|
||||||
|
parent: IContainerModel,
|
||||||
|
pattern: IPattern,
|
||||||
|
i: number,
|
||||||
|
configs: Map<string, IAvailableContainer>,
|
||||||
|
patterns: Map<string, IPattern>
|
||||||
|
): Node | undefined {
|
||||||
const childId: string = pattern.children[i];
|
const childId: string = pattern.children[i];
|
||||||
|
|
||||||
const child = GetPattern(childId, configs, patterns);
|
const child = GetPattern(childId, configs, patterns);
|
||||||
|
|
||||||
if (child === undefined) {
|
if (child === undefined) {
|
||||||
continue;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextNode: Node = {
|
return {
|
||||||
containerOrPattern: child,
|
containerOrPattern: child,
|
||||||
parent
|
parent
|
||||||
};
|
};
|
||||||
|
|
||||||
queue.push(nextNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Node {
|
interface Node {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue