Saving data from compound blocks

This commit is contained in:
Knut Sveidqvist 2023-09-01 15:33:38 +02:00
parent aa7f5a8387
commit 8a55b212a2
4 changed files with 85 additions and 73 deletions

View File

@ -18,48 +18,46 @@ import { log } from '../../logger.js';
// export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0? // export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0?
// Initialize the node database for simple lookups // Initialize the node database for simple lookups
let nodeDatabase: Record<string, Node> = {}; let blockDatabase: Record<string, Block> = {};
const blockDatabase: Record<string, Block> = {};
const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
for (const block of blockList) {
if (block.type === 'column-setting') {
const columns = block.columns || -1;
parent.columns = columns;
} else {
if (!block.label) {
block.label = block.id;
}
blockDatabase[block.id] = block;
if (block.children) {
populateBlockDatabase(block.children, block);
}
}
}
};
// Function to get a node by its id // Function to get a node by its id
type IGetNodeById = (id: string) => Block | undefined; type IGetNodeById = (id: string) => Block | undefined;
export const getNodeById = (id: string): Block | undefined => { export const getBlockById = (id: string): Block | undefined => {
console.log(id, nodeDatabase);
return blockDatabase[id]; return blockDatabase[id];
}; };
// TODO: Convert to generic TreeNode type? Convert to class? // TODO: Convert to generic TreeNode type? Convert to class?
let rootBlock = { id: 'root', children: [] as Block[], columns: -1 };
let blocks: Block[] = []; let blocks: Block[] = [];
const links: Link[] = []; const links: Link[] = [];
// let rootBlock = { id: 'root', children: [], columns: -1 } as Block; let rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
let currentBlock = rootBlock;
const clear = (): void => { const clear = (): void => {
log.info('Clear called'); log.info('Clear called');
// rootBlocks = [];
blocks = [] as Block[];
commonClear(); commonClear();
rootBlock = { id: 'root', children: [], columns: -1 }; rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
currentBlock = rootBlock; blockDatabase = { root: rootBlock };
nodeDatabase = {}; blocks = [] as Block[];
blockDatabase[rootBlock.id] = rootBlock;
}; };
// type IAddBlock = (block: Block) => Block;
// const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
// log.info('addBlock', block, parent);
// if (parent) {
// parent.children ??= [];
// parent.children.push(block);
// } else {
// rootBlock.children.push(block);
// }
// blocks.push(block);
// return block;
// };
type ITypeStr2Type = (typeStr: string) => BlockType; type ITypeStr2Type = (typeStr: string) => BlockType;
export function typeStr2Type(typeStr: string) { export function typeStr2Type(typeStr: string) {
// TODO: add all types // TODO: add all types
@ -74,6 +72,7 @@ export function typeStr2Type(typeStr: string) {
} }
let cnt = 0; let cnt = 0;
type IGenerateId = () => string;
export const generateId = () => { export const generateId = () => {
cnt++; cnt++;
return 'id-' + Math.random().toString(36).substr(2, 12) + '-' + cnt; return 'id-' + Math.random().toString(36).substr(2, 12) + '-' + cnt;
@ -96,13 +95,15 @@ export const addBlock = (_id: string, _label?: string, type?: BlockType) => {
blockDatabase[node.id] = node; blockDatabase[node.id] = node;
// currentBlock.children ??= []; // currentBlock.children ??= [];
// currentBlock.children.push(node); // currentBlock.children.push(node);
// console.log('currentBlock', currentBlock.children, nodeDatabase); // log.info('currentBlock', currentBlock.children, nodeDatabase);
console.log('addNode called:', id, label, type, node); log.info('addNode called:', id, label, type, node);
return node; return node;
}; };
type ISetHierarchy = (block: Block[]) => void; type ISetHierarchy = (block: Block[]) => void;
const setHierarchy = (block: Block[]): void => { const setHierarchy = (block: Block[]): void => {
populateBlockDatabase(block, rootBlock);
log.info('blockdb', JSON.stringify(blockDatabase, null, 2));
blocks = block; blocks = block;
}; };
@ -115,7 +116,6 @@ const addLink: IAddLink = (link: Link): Link => {
type ISetColumns = (columnsStr: string) => void; type ISetColumns = (columnsStr: string) => void;
const setColumns = (columnsStr: string): void => { const setColumns = (columnsStr: string): void => {
const columns = columnsStr === 'auto' ? -1 : parseInt(columnsStr); const columns = columnsStr === 'auto' ? -1 : parseInt(columnsStr);
currentBlock!.columns = columns;
}; };
const getBlock = (id: string, blocks: Block[]): Block | undefined => { const getBlock = (id: string, blocks: Block[]): Block | undefined => {
@ -149,8 +149,8 @@ const getColumns = (blockid: string): number => {
type IGetBlocks = () => Block[]; type IGetBlocks = () => Block[];
const getBlocks: IGetBlocks = () => { const getBlocks: IGetBlocks = () => {
// console.log('Block in test', rootBlock.children || []); // log.info('Block in test', rootBlock.children || []);
console.log('Block in test', blocks, blocks[0].id); log.info('Block in test', blocks, blocks[0].id);
return blocks || []; return blocks || [];
}; };
@ -172,7 +172,8 @@ export interface BlockDB extends DiagramDB {
getColumns: IGetColumns; getColumns: IGetColumns;
typeStr2Type: ITypeStr2Type; typeStr2Type: ITypeStr2Type;
setHierarchy: ISetHierarchy; setHierarchy: ISetHierarchy;
getNodeById: IGetNodeById; getBlockById: IGetNodeById;
generateId: IGenerateId;
} }
const db: BlockDB = { const db: BlockDB = {
@ -184,7 +185,7 @@ const db: BlockDB = {
getBlocks, getBlocks,
getLinks, getLinks,
setHierarchy, setHierarchy,
getNodeById, getBlockById,
// getAccTitle, // getAccTitle,
// setAccTitle, // setAccTitle,
// getAccDescription, // getAccDescription,
@ -194,6 +195,7 @@ const db: BlockDB = {
setColumns, setColumns,
getColumns, getColumns,
clear, clear,
generateId,
}; };
export default db; export default db;

View File

@ -22,7 +22,8 @@ export type BlockType =
| 'cylinder' | 'cylinder'
| 'group' | 'group'
| 'doublecircle' | 'doublecircle'
| 'composite'; | 'composite'
| 'column-setting';
export interface Block { export interface Block {
id: string; id: string;

View File

@ -138,7 +138,7 @@ seperator
; ;
start: BLOCK_DIAGRAM_KEY document EOF start: BLOCK_DIAGRAM_KEY document EOF
{console.log('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); } {yy.getLogger().info('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); }
; ;
@ -180,16 +180,16 @@ statement
; ;
nodeStatement nodeStatement
: nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id); $$ = {id: $1.id}; } : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); $$ = {id: $1.id}; }
| node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); $$ = {id: $1.id}; } | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1)}; }
; ;
columnsStatement columnsStatement
: COLUMNS { yy.getLogger().info("COLUMNS: ", $1);yy.setColumns($1); } : COLUMNS { yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } }
; ;
blockStatement blockStatement
: block document end { console.log('Rule: blockStatement : ', $1, $2, $3); const block = yy.addBlock(undefined, undefined, 'composite'); $$ = { id: block.id, children: $2 }; } : block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:id, children: $2 }; }
; ;

View File

@ -21,7 +21,7 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
expect(blocks.length).toBe(1); expect(blocks.length).toBe(1);
expect(blocks[0].ID).toBe('id'); expect(blocks[0].id).toBe('id');
expect(blocks[0].label).toBe('id'); expect(blocks[0].label).toBe('id');
}); });
it('a node with a square shape and a label', async () => { it('a node with a square shape and a label', async () => {
@ -32,7 +32,7 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
expect(blocks.length).toBe(1); expect(blocks.length).toBe(1);
expect(blocks[0].ID).toBe('id'); expect(blocks[0].id).toBe('id');
expect(blocks[0].label).toBe('A label'); expect(blocks[0].label).toBe('A label');
expect(blocks[0].type).toBe('square'); expect(blocks[0].type).toBe('square');
}); });
@ -45,10 +45,10 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
expect(blocks.length).toBe(2); expect(blocks.length).toBe(2);
expect(blocks[0].ID).toBe('id1'); expect(blocks[0].id).toBe('id1');
expect(blocks[0].label).toBe('id1'); expect(blocks[0].label).toBe('id1');
expect(blocks[0].type).toBe('square'); expect(blocks[0].type).toBe('square');
expect(blocks[1].ID).toBe('id2'); expect(blocks[1].id).toBe('id2');
expect(blocks[1].label).toBe('id2'); expect(blocks[1].label).toBe('id2');
expect(blocks[1].type).toBe('square'); expect(blocks[1].type).toBe('square');
}); });
@ -62,13 +62,13 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
expect(blocks.length).toBe(3); expect(blocks.length).toBe(3);
expect(blocks[0].ID).toBe('id1'); expect(blocks[0].id).toBe('id1');
expect(blocks[0].label).toBe('id1'); expect(blocks[0].label).toBe('id1');
expect(blocks[0].type).toBe('square'); expect(blocks[0].type).toBe('square');
expect(blocks[1].ID).toBe('id2'); expect(blocks[1].id).toBe('id2');
expect(blocks[1].label).toBe('id2'); expect(blocks[1].label).toBe('id2');
expect(blocks[1].type).toBe('square'); expect(blocks[1].type).toBe('square');
expect(blocks[2].ID).toBe('id3'); expect(blocks[2].id).toBe('id3');
expect(blocks[2].label).toBe('id3'); expect(blocks[2].label).toBe('id3');
expect(blocks[2].type).toBe('square'); expect(blocks[2].type).toBe('square');
}); });
@ -81,10 +81,10 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
expect(blocks.length).toBe(2); expect(blocks.length).toBe(2);
expect(blocks[0].ID).toBe('id'); expect(blocks[0].id).toBe('id');
expect(blocks[0].label).toBe('A label'); expect(blocks[0].label).toBe('A label');
expect(blocks[0].type).toBe('square'); expect(blocks[0].type).toBe('square');
expect(blocks[1].ID).toBe('id2'); expect(blocks[1].id).toBe('id2');
expect(blocks[1].label).toBe('id2'); expect(blocks[1].label).toBe('id2');
expect(blocks[1].type).toBe('square'); expect(blocks[1].type).toBe('square');
}); });
@ -152,24 +152,32 @@ describe('Block diagram', function () {
it('compound blocks 2', async () => { it('compound blocks 2', async () => {
const str = `block-beta const str = `block-beta
block block
aBlock["Block"] aBlock["ABlock"]
bBlock["Block"] bBlock["BBlock"]
end end
`; `;
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
console.log('blocks', blocks);
expect(blocks.length).toBe(1); expect(blocks.length).toBe(1);
expect(blocks[0].children.length).toBe(2); expect(blocks[0].children.length).toBe(2);
expect(blocks[0].id).toBe('id'); expect(blocks[0].id).not.toBe(undefined);
expect(blocks[0].label).toBe('A label'); expect(blocks[0].label).toBe(blocks[0].id);
expect(blocks[0].type).toBe('square'); expect(blocks[0].type).toBe('composite');
// expect(blocks[1].ID).toBe('id2');
// expect(blocks[1].label).toBe('id2'); const aBlock = blocks[0].children[0];
// expect(blocks[1].type).toBe('square');
expect(aBlock.id).not.toBe(aBlock);
expect(aBlock.label).toBe('ABlock');
expect(aBlock.type).toBe('square');
const bBlock = blocks[0].children[1];
expect(bBlock.id).not.toBe(bBlock);
expect(bBlock.label).toBe('BBlock');
expect(bBlock.type).toBe('square');
}); });
it.only('compound blocks', async () => { it('compound blocks of compound blocks', async () => {
const str = `block-beta const str = `block-beta
block block
aBlock["ABlock"] aBlock["ABlock"]
@ -182,29 +190,30 @@ describe('Block diagram', function () {
block.parse(str); block.parse(str);
const blocks = db.getBlocks(); const blocks = db.getBlocks();
const aBlockPos = blocks[0].children[0]; const aBlock = blocks[0].children[0];
const bBlockPos = blocks[0].children[1].children[0]; const secondComposite = blocks[0].children[1];
const bBlock = blocks[0].children[1].children[0];
const root = db.getNodeById(blocks[0].id);
expect(blocks.length).toBe(1);
expect(blocks[0].id).not.toBe(undefined);
expect(root?.label).toBe(blocks[0].id);
expect(blocks[0].children.length).toBe(2); expect(blocks[0].children.length).toBe(2);
expect(root?.type).toBe('composite'); expect(blocks[0].id).not.toBe(undefined);
expect(blocks[0].label).toBe(blocks[0].id);
expect(blocks[0].type).toBe('composite');
const aBlock = db.getNodeById(aBlockPos.id); expect(secondComposite.children.length).toBe(1);
console.log('aBlock', aBlock); expect(secondComposite.id).not.toBe(undefined);
expect(aBlock?.label).toBe('ABlock'); expect(secondComposite.label).toBe(secondComposite.id);
expect(aBlock?.type).toBe('square'); expect(secondComposite.type).toBe('composite');
const bBlock = db.getNodeById(bBlockPos.id); expect(aBlock.id).not.toBe(aBlock);
expect(aBlock.label).toBe('ABlock');
expect(aBlock.type).toBe('square');
expect(bBlock.id).toBe('bBlock'); expect(bBlock.id).not.toBe(bBlock);
expect(bBlock.label).toBe('BBlock'); expect(bBlock.label).toBe('BBlock');
expect(bBlock.type).toBe('square'); expect(bBlock.type).toBe('square');
}); });
it.skip('compound blocks with title', async () => { it('compound blocks with title', async () => {
const str = `block const str = `block-beta
block compoundBlock["Compound block"] block compoundBlock["Compound block"]
columns 1 columns 1
block2["Block 1"] block2["Block 1"]