From 20d7fa77423ef1ef55a5c2707e0d5dbedfdc34b1 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Thu, 18 Jan 2024 22:40:15 +0800 Subject: [PATCH 01/18] #3869 Left-to-right ("Snake-like") layout for RNA --- .../render/renderers/PolymerBondRenderer.ts | 65 ++- .../render/renderers/RenderersManager.ts | 80 +--- .../domain/entities/DrawingEntitiesManager.ts | 374 ++++++++++++++---- .../src/domain/helpers/monomers.ts | 48 +++ 4 files changed, 428 insertions(+), 139 deletions(-) diff --git a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts index eab72cbb90..9167d06a32 100644 --- a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts @@ -4,15 +4,20 @@ import { DrawingEntity } from 'domain/entities/DrawingEntity'; import assert from 'assert'; import { D3SvgElementSelection } from 'application/render/types'; import { editorEvents } from 'application/editor/editorEvents'; -import { Vec2 } from 'domain/entities'; +import { Phosphate, Sugar, Vec2 } from 'domain/entities'; import { Peptide } from 'domain/entities/Peptide'; import { Chem } from 'domain/entities/Chem'; import { BaseMonomer } from 'domain/entities/BaseMonomer'; import { SnakeMode } from 'application/editor/modes/internal'; import { Coordinates } from 'application/editor/shared/coordinates'; +import { + getNextMonomerInChain, + getRnaBaseMonomerFromSugar, +} from 'domain/helpers/monomers'; const LINE_FROM_MONOMER_LENGTH = 15; const VERTICAL_LINE_LENGTH = 42; +const RNA_CHAIN_VERTICAL_LINE_LENGTH = 144; const CORNER_LENGTH = 8; const DOUBLE_CORNER_LENGTH = CORNER_LENGTH * 2; enum LINE_DIRECTION { @@ -36,7 +41,12 @@ export class PolymerBondRenderer extends BaseRenderer { } private isSnakeBondAvailableForMonomer(monomer?: BaseMonomer) { - return monomer instanceof Peptide || monomer instanceof Chem; + return ( + monomer instanceof Peptide || + monomer instanceof Chem || + monomer instanceof Sugar || + monomer instanceof Phosphate + ); } get isSnake() { @@ -149,7 +159,18 @@ export class PolymerBondRenderer extends BaseRenderer { } private getMonomerHeight() { - return this.polymerBond.firstMonomer.renderer?.monomerSize.width ?? 0; + const isRnaChain = + this.polymerBond.firstMonomer instanceof Sugar || + this.polymerBond.firstMonomer instanceof Phosphate; + + if (isRnaChain) { + const sugar = getNextMonomerInChain(this.polymerBond.firstMonomer); + return ( + (sugar?.renderer?.monomerSize?.height ?? 0) + + (getRnaBaseMonomerFromSugar(sugar)?.renderer?.monomerSize?.height ?? 0) + ); + } + return this.polymerBond.firstMonomer.renderer?.monomerSize.height ?? 0; } public isMonomersOnSameHorizontalLine() { @@ -176,6 +197,12 @@ export class PolymerBondRenderer extends BaseRenderer { this.polymerBond.firstMonomer.getPotentialAttachmentPointByBond( this.polymerBond, ) === 'R1'; + const verticalLineLength = + this.polymerBond.firstMonomer instanceof Sugar || + this.polymerBond.firstMonomer instanceof Phosphate + ? RNA_CHAIN_VERTICAL_LINE_LENGTH + : VERTICAL_LINE_LENGTH; + if (this.isSecondMonomerBottomRight(startPosition, endPosition)) { if ( isR1TheCurrentAttachmentpointOfFirstMonomer && @@ -233,7 +260,13 @@ export class PolymerBondRenderer extends BaseRenderer { LINE_FROM_MONOMER_LENGTH - this.getMonomerWidth() / 2, ); - } else if (this.isSecondMonomerBottomLeft(startPosition, endPosition)) { + } else if ( + this.isSecondMonomerBottomLeft( + startPosition, + endPosition, + verticalLineLength, + ) + ) { if ( isR1TheCurrentAttachmentpointOfFirstMonomer && reCheckAttachmentpoint @@ -247,7 +280,7 @@ export class PolymerBondRenderer extends BaseRenderer { startPosition, ); this.addLineFromLeftToBottom(); - this.addLine(LINE_DIRECTION.Vertical, VERTICAL_LINE_LENGTH); + this.addLine(LINE_DIRECTION.Vertical, verticalLineLength); this.addLineFromTopToLeft(); this.addLine( LINE_DIRECTION.Horizontal, @@ -264,7 +297,7 @@ export class PolymerBondRenderer extends BaseRenderer { endPosition.y - startPosition.y - CORNER_LENGTH * 4 - - VERTICAL_LINE_LENGTH, + verticalLineLength, ); this.addLineFromTopToRight(); this.addLine( @@ -307,7 +340,9 @@ export class PolymerBondRenderer extends BaseRenderer { LINE_DIRECTION.Horizontal, LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() / 2, ); - } else if (this.isSecondMonomerLeft(startPosition, endPosition)) { + } else if ( + this.isSecondMonomerLeft(startPosition, endPosition, verticalLineLength) + ) { if ( isR1TheCurrentAttachmentpointOfFirstMonomer && reCheckAttachmentpoint @@ -364,10 +399,14 @@ export class PolymerBondRenderer extends BaseRenderer { ); } - private isSecondMonomerBottomLeft(startPosition, endPosition): boolean { + private isSecondMonomerBottomLeft( + startPosition, + endPosition, + VerticalLineLength, + ): boolean { return ( endPosition.y - startPosition.y >= - 2 * (VERTICAL_LINE_LENGTH + DOUBLE_CORNER_LENGTH) && + 2 * (VerticalLineLength + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); @@ -381,11 +420,15 @@ export class PolymerBondRenderer extends BaseRenderer { ); } - private isSecondMonomerLeft(startPosition, endPosition): boolean { + private isSecondMonomerLeft( + startPosition, + endPosition, + VerticalLineLength, + ): boolean { return ( startPosition.y - endPosition.y < 0 && startPosition.y - endPosition.y > - -2 * (VERTICAL_LINE_LENGTH + DOUBLE_CORNER_LENGTH) && + -2 * (VerticalLineLength + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); diff --git a/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts b/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts index 1d969c9928..7f79281d96 100644 --- a/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts +++ b/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts @@ -15,6 +15,12 @@ import { } from 'application/render'; import { notifyRenderComplete } from 'application/render/internal'; import { Peptide, Sugar, RNABase, Phosphate } from 'domain/entities'; +import { + checkIsR2R1Connection, + getNextMonomerInChain, + getRnaBaseMonomerFromSugar, + isMonomerBeginningOfChain, +} from 'domain/helpers/monomers'; export class RenderersManager { private theme; @@ -124,21 +130,6 @@ export class RenderersManager { } } - private getNextMonomerInChain(monomer?: BaseMonomer) { - if (!monomer) return undefined; - - const r2PolymerBond = monomer.attachmentPointsToBonds.R2; - - return r2PolymerBond?.getAnotherMonomer(monomer); - } - - private isR2R1Connection(monomer, nextMonomer) { - return ( - nextMonomer.attachmentPointsToBonds.R1?.getAnotherMonomer(nextMonomer) === - monomer - ); - } - private recalculatePeptideChainEnumeration( peptideRenderer: PeptideRenderer, currentEnumeration = 1, @@ -146,13 +137,13 @@ export class RenderersManager { peptideRenderer.setEnumeration(currentEnumeration); peptideRenderer.redrawEnumeration(); - const nextMonomer = this.getNextMonomerInChain(peptideRenderer.monomer); + const nextMonomer = getNextMonomerInChain(peptideRenderer.monomer); if (!(nextMonomer instanceof Peptide)) { return; } - const isR2R1Connection = this.isR2R1Connection( + const isR2R1Connection = checkIsR2R1Connection( peptideRenderer.monomer, nextMonomer, ); @@ -175,8 +166,8 @@ export class RenderersManager { ) { let currentEnumeration = _currentEnumeration; if (rnaComponentRenderer instanceof SugarRenderer) { - const rnaBaseMonomer = this.getRnaBaseMonomerFromSugar( - rnaComponentRenderer as SugarRenderer, + const rnaBaseMonomer = getRnaBaseMonomerFromSugar( + rnaComponentRenderer.monomer as Sugar, ); if (rnaBaseMonomer instanceof RNABase) { rnaBaseMonomer.renderer?.setEnumeration(currentEnumeration); @@ -185,9 +176,7 @@ export class RenderersManager { } } - const nextMonomer = this.getNextMonomerInChain( - rnaComponentRenderer.monomer, - ); + const nextMonomer = getNextMonomerInChain(rnaComponentRenderer.monomer); if ( !(nextMonomer instanceof Sugar) && @@ -196,7 +185,7 @@ export class RenderersManager { return; } - const isR2R1Connection = this.isR2R1Connection( + const isR2R1Connection = checkIsR2R1Connection( rnaComponentRenderer.monomer, nextMonomer, ); @@ -213,45 +202,20 @@ export class RenderersManager { ); } - private isMonomerBeginningOfChain( - monomer: BaseMonomer, - MonomerTypes: Array, - ) { - const r1PolymerBond = monomer.attachmentPointsToBonds.R1; - const previousMonomer = r1PolymerBond?.getAnotherMonomer(monomer); - const isPreviousMonomerPartOfChain = - previousMonomer && - !MonomerTypes.some( - (MonomerType) => previousMonomer instanceof MonomerType, - ); - const previousConnectionNotR2 = - r1PolymerBond && - previousMonomer?.getAttachmentPointByBond(r1PolymerBond) !== 'R2'; - - return ( - ((monomer.isAttachmentPointExistAndFree('R1') || - !monomer.hasAttachmentPoint('R1')) && - monomer.hasBonds) || - previousConnectionNotR2 || - isPreviousMonomerPartOfChain - ); - } - private recalculatePeptideEnumeration(peptideRenderer: PeptideRenderer) { if (!peptideRenderer.monomer.hasBonds) { peptideRenderer.setEnumeration(null); peptideRenderer.redrawEnumeration(); } - if (!this.isMonomerBeginningOfChain(peptideRenderer.monomer, [Peptide])) - return; + if (!isMonomerBeginningOfChain(peptideRenderer.monomer, [Peptide])) return; this.recalculatePeptideChainEnumeration(peptideRenderer); } private recalculateRnaEnumeration(rnaComponentRenderer: BaseMonomerRenderer) { if ( - !this.isMonomerBeginningOfChain(rnaComponentRenderer.monomer, [ + !isMonomerBeginningOfChain(rnaComponentRenderer.monomer, [ Phosphate, Sugar, ]) @@ -283,8 +247,8 @@ export class RenderersManager { } private isOnlyPartOfRnaChain(sugar: Sugar) { - const phosphate = this.getNextMonomerInChain(sugar); - const nextMonomerAfterPhospate = this.getNextMonomerInChain(phosphate); + const phosphate = getNextMonomerInChain(sugar); + const nextMonomerAfterPhospate = getNextMonomerInChain(phosphate); return !sugar.attachmentPointsToBonds.R1 && !nextMonomerAfterPhospate; } @@ -299,8 +263,8 @@ export class RenderersManager { monomerRenderer.reDrawChainBeginning(); } if (monomerRenderer instanceof SugarRenderer) { - const rnaBaseMonomer = this.getRnaBaseMonomerFromSugar( - monomerRenderer as SugarRenderer, + const rnaBaseMonomer = getRnaBaseMonomerFromSugar( + monomerRenderer.monomer as Sugar, ); if ( rnaBaseMonomer instanceof RNABase && @@ -317,14 +281,6 @@ export class RenderersManager { this.needRecalculateMonomersBeginning = false; } - private getRnaBaseMonomerFromSugar(sugarRenderer: SugarRenderer) { - const r3PolymerBond = sugarRenderer.monomer.attachmentPointsToBonds.R3; - const rnaBaseMonomer = r3PolymerBond?.getAnotherMonomer( - sugarRenderer.monomer, - ); - return rnaBaseMonomer; - } - public finishPolymerBondCreation(polymerBond: PolymerBond) { assert(polymerBond.secondMonomer); diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 09d470f146..f115ab999c 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -11,6 +11,9 @@ import { Pool, Chem, SGroupForest, + RNABase, + Sugar, + Phosphate, } from 'domain/entities'; import { AttachmentPointHoverOperation, @@ -36,9 +39,15 @@ import { import { monomerFactory } from 'application/editor/operations/monomer/monomerFactory'; import { Coordinates } from 'application/editor'; import { getCurrentCenterPointOfCanvas } from 'application/utils'; +import { + getNextMonomerInChain, + getRnaBaseMonomerFromSugar, + isMonomerBeginningOfChain, +} from 'domain/helpers/monomers'; const HORIZONTAL_DISTANCE_FROM_MONOMER = 50; const VERTICAL_DISTANCE_FROM_MONOMER = 60; +const RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER = 160; const DISTANCE_FROM_RIGHT = 70; const DISTANCE_BETWEEN_MONOMERS = 30; const MONOMER_START_X_POSITION = 70; @@ -53,9 +62,16 @@ type RnaPresetAdditionParams = { phosphatePosition: Vec2 | undefined; }; +type Nucleotide = { + sugar: Sugar; + rnaBase: RNABase | undefined; + phosphate: Phosphate | undefined; +}; + export class DrawingEntitiesManager { public monomers: Map = new Map(); public polymerBonds: Map = new Map(); + public nucleotides: RnaPresetAdditionParams[] = []; public micromoleculesHiddenEntities: Struct = new Struct(); get selectedEntities() { return this.allEntities.filter( @@ -831,36 +847,42 @@ export class DrawingEntitiesManager { return monomer; } - private rearrangeChain( + public getNucleotideSize(nucleotide: Nucleotide) { + const width = + (nucleotide.sugar.renderer?.width || 0) + + (nucleotide.phosphate?.renderer?.width || 0) + + 45; + const height = + (nucleotide.sugar.renderer?.height || 0) + + (nucleotide.rnaBase?.renderer?.height || 0) + + 45; + return { width, height }; + } + + private reArrangeChain( monomer: BaseMonomer, - initialPosition: Vec2, + lastPosition: Vec2, canvasWidth: number, rearrangedMonomersSet: Set = new Set(), - isNextChain = false, + maxVerticalDistance: number, ) { const command = new Command(); const monomerWidth = monomer.renderer?.monomerSize.width ?? 0; const monomerHeight = monomer.renderer?.monomerSize.height ?? 0; const heightMonomerWithBond = monomerHeight + VERTICAL_DISTANCE_FROM_MONOMER; - const oldMonomerPosition = monomer.position; - const newPosition = isNextChain - ? new Vec2( - MONOMER_START_X_POSITION, - initialPosition.y + heightMonomerWithBond, - ) - : initialPosition; + maxVerticalDistance = Math.max(maxVerticalDistance, heightMonomerWithBond); + const oldMonomerPosition = monomer.position; const operation = new MonomerMoveOperation( this.rearrangeChainModelChange.bind( this, monomer, - Coordinates.canvasToModel(newPosition), + Coordinates.canvasToModel(lastPosition), ), this.rearrangeChainModelChange.bind(this, monomer, oldMonomerPosition), ); command.addOperation(operation); - let lastPosition = newPosition; rearrangedMonomersSet.add(monomer.id); for (const attachmentPointName in monomer.attachmentPointsToBonds) { @@ -875,67 +897,177 @@ export class DrawingEntitiesManager { if (rearrangedMonomersSet.has(nextMonomer.id)) { continue; } + lastPosition = this.getNextPosition( + lastPosition, + monomerWidth, + heightMonomerWithBond, + canvasWidth, + ); if ( (attachmentPointName === 'R2' && nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1') || (attachmentPointName === 'R1' && nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2') ) { - const isMonomerFitCanvas = - newPosition.x + - monomerWidth + - DISTANCE_BETWEEN_MONOMERS + - HORIZONTAL_DISTANCE_FROM_MONOMER + - DISTANCE_FROM_RIGHT < - canvasWidth; - let rearrangeResult; - if (isMonomerFitCanvas) { - rearrangeResult = this.rearrangeChain( - nextMonomer, - new Vec2({ - x: - newPosition.x + monomerWidth + HORIZONTAL_DISTANCE_FROM_MONOMER, - y: newPosition.y, - }), - canvasWidth, - rearrangedMonomersSet, - ); - } else { - rearrangeResult = this.rearrangeChain( - nextMonomer, - new Vec2({ - x: MONOMER_START_X_POSITION, - y: newPosition.y + heightMonomerWithBond, - }), - canvasWidth, - rearrangedMonomersSet, - ); - } + const rearrangeResult = this.reArrangeChainInRecursive( + nextMonomer, + lastPosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, + ); lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; command.merge(rearrangeResult.command); } else { const diff = Vec2.diff(oldMonomerPosition, monomer.position); const pos = Vec2.diff(nextMonomer.position, diff); - const rearrangeResult = this.rearrangeChain( + const rearrangeResult = this.reArrangeChainInRecursive( nextMonomer, Coordinates.modelToCanvas(pos), canvasWidth, rearrangedMonomersSet, + maxVerticalDistance, ); + lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; command.merge(rearrangeResult.command); } } + return { command, lastPosition, maxVerticalDistance }; + } - return { command, lastPosition }; + private reArrangeRnaChain( + nucleotide: Nucleotide, + lastPosition: Vec2, + canvasWidth: number, + rearrangedMonomersSet: Set = new Set(), + maxVerticalDistance: number, + ) { + const command = new Command(); + const nucleotideSize = this.getNucleotideSize(nucleotide); + const height = nucleotideSize.height; + const width = nucleotideSize.width; + const heightWithBond = height + RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER; + maxVerticalDistance = Math.max(maxVerticalDistance, heightWithBond); + + const oldSugarPosition = nucleotide.sugar.position; + const newPositionOfModel = Coordinates.canvasToModel(lastPosition); + const phosphatePosition = Coordinates.canvasToModel( + new Vec2( + lastPosition.x + (nucleotide.sugar.renderer?.width ?? 0) + 45, + lastPosition.y, + ), + ); + const rnaBasePosition = Coordinates.canvasToModel( + new Vec2( + lastPosition.x, + lastPosition.y + (nucleotide.sugar.renderer?.height ?? 0) + 45, + ), + ); + + this.addRnaOperations( + command, + oldSugarPosition, + newPositionOfModel, + nucleotide.sugar, + ); + this.addRnaOperations( + command, + nucleotide.phosphate?.position, + phosphatePosition, + nucleotide.phosphate, + ); + this.addRnaOperations( + command, + nucleotide.rnaBase?.position, + rnaBasePosition, + nucleotide.rnaBase, + ); + Object.keys(nucleotide).forEach((key) => { + rearrangedMonomersSet.add(nucleotide[key].id); + }); + const polymerBond = nucleotide.phosphate?.attachmentPointsToBonds.R2; + if (!polymerBond) { + return { + command, + lastPosition, + maxVerticalDistance, + }; + } + const nextMonomer = + polymerBond.secondMonomer === nucleotide.phosphate + ? polymerBond.firstMonomer + : polymerBond.secondMonomer; + if (!nextMonomer) { + return { + command, + lastPosition, + maxVerticalDistance, + }; + } + if (rearrangedMonomersSet.has(nextMonomer.id)) { + return command; + } + lastPosition = this.getNextPosition( + lastPosition, + width, + heightWithBond, + canvasWidth, + ); + const rearrangeResult = this.reArrangeChainInRecursive( + nextMonomer, + lastPosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, + ); + lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; + command.merge(rearrangeResult.command); + return { command, lastPosition, maxVerticalDistance }; + } + + private addRnaOperations( + command: Command, + oldMonomerPosition: Vec2 | undefined, + newPosition: Vec2 | undefined, + monomer?: BaseMonomer, + ) { + if (!monomer || !oldMonomerPosition || !newPosition) { + return; + } + const operation = new MonomerMoveOperation( + this.rearrangeChainModelChange.bind(this, monomer, newPosition), + this.rearrangeChainModelChange.bind(this, monomer, oldMonomerPosition), + ); + command.addOperation(operation); } public reArrangeChains(canvasWidth: number, isSnakeMode: boolean) { const command = new Command(); if (isSnakeMode) { - command.merge(this.reArrangeMonomers(canvasWidth)); + const firstMonomersInChains = this.getFirstMonomersInChains([ + Peptide, + Chem, + ]); + const firstRnaMonomersInChains = this.getFirstMonomersInChains([ + Sugar, + Phosphate, + ]); + const firstMonomers = firstMonomersInChains.concat( + firstRnaMonomersInChains, + ); + firstMonomers.sort( + (monomer1, monomer2) => + monomer1.position.x + + monomer1.position.y - + (monomer2.position.x + monomer2.position.y), + ); + const monomerCommand = this.reArrangeMonomers(canvasWidth, firstMonomers); + command.merge(monomerCommand); } command.merge(this.redrawBonds()); - return command; } @@ -959,9 +1091,13 @@ export class DrawingEntitiesManager { return command; } - public reArrangeMonomers(canvasWidth: number) { - const monomersList = Array.from(this.monomers.values()).filter( - (monomer) => monomer instanceof Peptide || monomer instanceof Chem, + public getFirstMonomersInChains( + MonomerTypes: Array< + typeof Peptide | typeof Chem | typeof Phosphate | typeof Sugar + >, + ) { + const monomersList = Array.from(this.monomers.values()).filter((monomer) => + MonomerTypes.some((MonomerType) => monomer instanceof MonomerType), ); const firstMonomersInChains = monomersList.filter((monomer) => { @@ -979,19 +1115,7 @@ export class DrawingEntitiesManager { ); }); - firstMonomersInChains.sort((monomer1, monomer2) => { - if ( - monomer2.position.x + monomer2.position.y < - monomer1.position.x + monomer1.position.y - ) { - return -1; - } else { - return 1; - } - }); - const filteredFirstMonomersInChains: BaseMonomer[] = []; - firstMonomersInChains.forEach((monomer, monomerIndex) => { const currentMonomerChain: BaseMonomer[] = this.findChainByMonomer(monomer); @@ -1000,6 +1124,8 @@ export class DrawingEntitiesManager { (potentialFirstMonomer, potentialFirstMonomerIndex) => { if ( potentialFirstMonomerIndex > monomerIndex && + // TODO: which case could cause this scenario? (current chain contains other first monomers) + // Do i need to inplement this for rna chains? currentMonomerChain.includes(potentialFirstMonomer) ) { isFirstMonomerInChain = false; @@ -1010,27 +1136,123 @@ export class DrawingEntitiesManager { filteredFirstMonomersInChains.push(monomer); } }); + return filteredFirstMonomersInChains; + } + + public getFirstRnaMonomersInChains() { + // TODO: is this alright for get the rna backbone monomer? + const firstMonomersInChains = Array.from(this.monomers.values()).filter( + (monomer) => + (monomer instanceof Sugar || monomer instanceof Phosphate) && + isMonomerBeginningOfChain(monomer, [Sugar, Phosphate]), + ); + return firstMonomersInChains; + } + + public reArrangeChainInRecursive( + monomer: BaseMonomer, + lastPosition: Vec2, + canvasWidth: number, + rearrangedMonomersSet: Set = new Set(), + maxVerticalDistance: number, + ) { const command = new Command(); + let rearrangeResult; + + if (monomer instanceof Sugar) { + const nucleotide = getNucleotideFromFirstMonomer(monomer); + if (nucleotide) { + rearrangeResult = this.reArrangeRnaChain( + nucleotide, + lastPosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, + ); + lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; + command.merge(rearrangeResult.command); + return { command, lastPosition, maxVerticalDistance }; + } + } + // TODO: if the first monomer is single sugar OR phosphate, snake-mode should still be applied to it + rearrangeResult = this.reArrangeChain( + monomer, + lastPosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, + ); + lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; + command.merge(rearrangeResult.command); + return { command, lastPosition, maxVerticalDistance }; + } + + public getNextPosition( + lastPosition: Vec2, + width: number, + height: number, + canvasWidth: number, + ) { + const isMonomerFitCanvas = + lastPosition.x + + width + + DISTANCE_BETWEEN_MONOMERS + + HORIZONTAL_DISTANCE_FROM_MONOMER + + DISTANCE_FROM_RIGHT < + canvasWidth; + + if (!isMonomerFitCanvas) { + return getFirstPosition(height, lastPosition); + } + + return new Vec2({ + x: lastPosition.x + width + HORIZONTAL_DISTANCE_FROM_MONOMER, + y: lastPosition.y, + }); + } + + public reArrangeMonomers(canvasWidth: number, firstMonomers: BaseMonomer[]) { let lastPosition = new Vec2({ x: MONOMER_START_X_POSITION, y: MONOMER_START_Y_POSITION, }); - - filteredFirstMonomersInChains.reverse().forEach((monomer, monomerIndex) => { - const rearrangeResult = this.rearrangeChain( + const command = new Command(); + // TODO: bonds connecting RNA monomers to the monomers of peptides or CHEMs should remain straight--no snake mode + // peptide monomers, CHEMs could also be in the front + firstMonomers.forEach((monomer) => { + const rearrangeResult = this.reArrangeChainInRecursive( monomer, lastPosition, canvasWidth, undefined, - monomerIndex !== 0, + 0, ); command.merge(rearrangeResult.command); lastPosition = rearrangeResult.lastPosition; + // need to calculate the vertical distance before the next row gets to display + // because the height of rna and peptide are different + lastPosition = getFirstPosition( + rearrangeResult.maxVerticalDistance, + lastPosition, + ); }); - return command; } + public getPhosphateFromRnaBase(baseMonomer: RNABase) { + const r1PolymerBond = baseMonomer.attachmentPointsToBonds.R1; + const sugarMonomer = r1PolymerBond?.getAnotherMonomer(baseMonomer); + if (sugarMonomer && sugarMonomer instanceof Sugar) { + const phosphate = getNextMonomerInChain(sugarMonomer); + if (phosphate && phosphate instanceof Phosphate) { + return phosphate; + } + } + return undefined; + } + public setMicromoleculesHiddenEntities(struct: Struct) { struct.mergeInto(this.micromoleculesHiddenEntities); this.micromoleculesHiddenEntities.atoms = new Pool(); @@ -1120,3 +1342,23 @@ export class DrawingEntitiesManager { return new Vec2((xmin + xmax) / 2, (ymin + ymax) / 2); } } +function getFirstPosition(height: number, lastPosition: Vec2) { + return new Vec2(MONOMER_START_X_POSITION, lastPosition.y + height); +} + +function getNucleotideFromFirstMonomer(monomer: BaseMonomer) { + if (monomer instanceof Sugar) { + const nextMonomer = getNextMonomerInChain(monomer); + const rnaBaseMonomer = getRnaBaseMonomerFromSugar(monomer); + const isNucleotide = + nextMonomer instanceof Phosphate && rnaBaseMonomer instanceof RNABase; + if (isNucleotide) { + return { + sugar: monomer, + phosphate: nextMonomer, + rnaBase: rnaBaseMonomer, + } as Nucleotide; + } + } + return null; +} diff --git a/packages/ketcher-core/src/domain/helpers/monomers.ts b/packages/ketcher-core/src/domain/helpers/monomers.ts index 60b3a5571b..f26aea3a02 100644 --- a/packages/ketcher-core/src/domain/helpers/monomers.ts +++ b/packages/ketcher-core/src/domain/helpers/monomers.ts @@ -1,5 +1,53 @@ +import { BaseMonomer, Peptide, Phosphate, Sugar } from 'domain/entities'; import { MonomerItemType } from 'domain/types'; export function getMonomerUniqueKey(monomer: MonomerItemType) { return `${monomer.props.MonomerName}___${monomer.props.Name}`; } + +export function checkIsR2R1Connection( + monomer: BaseMonomer, + nextMonomer: BaseMonomer, +) { + return ( + nextMonomer.attachmentPointsToBonds.R1?.getAnotherMonomer(nextMonomer) === + monomer + ); +} + +export function getNextMonomerInChain(monomer?: BaseMonomer) { + if (!monomer) return undefined; + + const r2PolymerBond = monomer.attachmentPointsToBonds.R2; + + return r2PolymerBond?.getAnotherMonomer(monomer); +} + +export function getRnaBaseMonomerFromSugar(monomer?: BaseMonomer) { + if (!monomer) return undefined; + const r3PolymerBond = monomer.attachmentPointsToBonds.R3; + const rnaBaseMonomer = r3PolymerBond?.getAnotherMonomer(monomer); + return rnaBaseMonomer; +} + +export function isMonomerBeginningOfChain( + monomer: BaseMonomer, + MonomerTypes: Array, +) { + const r1PolymerBond = monomer.attachmentPointsToBonds.R1; + const previousMonomer = r1PolymerBond?.getAnotherMonomer(monomer); + const isPreviousMonomerPartOfChain = + previousMonomer && + !MonomerTypes.some((MonomerType) => previousMonomer instanceof MonomerType); + const previousConnectionNotR2 = + r1PolymerBond && + previousMonomer?.getAttachmentPointByBond(r1PolymerBond) !== 'R2'; + + return ( + ((monomer.isAttachmentPointExistAndFree('R1') || + !monomer.hasAttachmentPoint('R1')) && + monomer.hasBonds) || + previousConnectionNotR2 || + isPreviousMonomerPartOfChain + ); +} From 4bff65c122d88c6c41e14b1e3bd60b688f07e540 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Fri, 19 Jan 2024 16:52:45 +0800 Subject: [PATCH 02/18] #3869 snake mode for rna chain --- .../render/renderers/PolymerBondRenderer.ts | 50 +++++++--- .../src/domain/entities/BaseMonomer.ts | 2 + .../domain/entities/DrawingEntitiesManager.ts | 94 +++++++++---------- 3 files changed, 84 insertions(+), 62 deletions(-) diff --git a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts index 9167d06a32..c5fbc3d223 100644 --- a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts @@ -49,11 +49,30 @@ export class PolymerBondRenderer extends BaseRenderer { ); } + private isMonomersTypeDifferent() { + return ( + (this.polymerBond.secondMonomer && + [Peptide, Chem].some( + (type) => this.polymerBond.firstMonomer instanceof type, + ) && + [Sugar, Phosphate].some( + (type) => this.polymerBond.secondMonomer instanceof type, + )) || + ([Peptide, Chem].some( + (type) => this.polymerBond.secondMonomer instanceof type, + ) && + [Sugar, Phosphate].some( + (type) => this.polymerBond.firstMonomer instanceof type, + )) + ); + } + get isSnake() { if ( !this.isSnakeBondAvailableForMonomer(this.polymerBond.firstMonomer) || (this.polymerBond.secondMonomer && - !this.isSnakeBondAvailableForMonomer(this.polymerBond.secondMonomer)) + !this.isSnakeBondAvailableForMonomer(this.polymerBond.secondMonomer)) || + this.isMonomersTypeDifferent() ) { return false; } @@ -197,11 +216,14 @@ export class PolymerBondRenderer extends BaseRenderer { this.polymerBond.firstMonomer.getPotentialAttachmentPointByBond( this.polymerBond, ) === 'R1'; - const verticalLineLength = - this.polymerBond.firstMonomer instanceof Sugar || - this.polymerBond.firstMonomer instanceof Phosphate - ? RNA_CHAIN_VERTICAL_LINE_LENGTH - : VERTICAL_LINE_LENGTH; + + // check if there is nucleotide in current row + const isBondConnectedWithNucleotide = + this.polymerBond.firstMonomer.isMonomerInRnaChainRow; + + const verticalLineLength = isBondConnectedWithNucleotide + ? RNA_CHAIN_VERTICAL_LINE_LENGTH + : VERTICAL_LINE_LENGTH; if (this.isSecondMonomerBottomRight(startPosition, endPosition)) { if ( @@ -400,13 +422,13 @@ export class PolymerBondRenderer extends BaseRenderer { } private isSecondMonomerBottomLeft( - startPosition, - endPosition, - VerticalLineLength, + startPosition: Vec2, + endPosition: Vec2, + verticalLineLength: number, ): boolean { return ( endPosition.y - startPosition.y >= - 2 * (VerticalLineLength + DOUBLE_CORNER_LENGTH) && + 2 * (verticalLineLength + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); @@ -421,14 +443,14 @@ export class PolymerBondRenderer extends BaseRenderer { } private isSecondMonomerLeft( - startPosition, - endPosition, - VerticalLineLength, + startPosition: Vec2, + endPosition: Vec2, + verticalLineLength: number, ): boolean { return ( startPosition.y - endPosition.y < 0 && startPosition.y - endPosition.y > - -2 * (VerticalLineLength + DOUBLE_CORNER_LENGTH) && + -2 * (verticalLineLength + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); diff --git a/packages/ketcher-core/src/domain/entities/BaseMonomer.ts b/packages/ketcher-core/src/domain/entities/BaseMonomer.ts index cae38ae57e..f25bf95ff8 100644 --- a/packages/ketcher-core/src/domain/entities/BaseMonomer.ts +++ b/packages/ketcher-core/src/domain/entities/BaseMonomer.ts @@ -29,6 +29,8 @@ export abstract class BaseMonomer extends DrawingEntity { public attachmentPointsVisible = false; public monomerItem: MonomerItemType; + public isMonomerInRnaChainRow = false; + constructor(monomerItem: MonomerItemType, _position?: Vec2) { super(_position); diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index f115ab999c..12fc92aade 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -42,7 +42,6 @@ import { getCurrentCenterPointOfCanvas } from 'application/utils'; import { getNextMonomerInChain, getRnaBaseMonomerFromSugar, - isMonomerBeginningOfChain, } from 'domain/helpers/monomers'; const HORIZONTAL_DISTANCE_FROM_MONOMER = 50; @@ -64,8 +63,8 @@ type RnaPresetAdditionParams = { type Nucleotide = { sugar: Sugar; - rnaBase: RNABase | undefined; - phosphate: Phosphate | undefined; + rnaBase: RNABase; + phosphate: Phosphate; }; export class DrawingEntitiesManager { @@ -872,7 +871,8 @@ export class DrawingEntitiesManager { const heightMonomerWithBond = monomerHeight + VERTICAL_DISTANCE_FROM_MONOMER; maxVerticalDistance = Math.max(maxVerticalDistance, heightMonomerWithBond); - + monomer.isMonomerInRnaChainRow = + maxVerticalDistance > heightMonomerWithBond; const oldMonomerPosition = monomer.position; const operation = new MonomerMoveOperation( this.rearrangeChainModelChange.bind( @@ -897,12 +897,14 @@ export class DrawingEntitiesManager { if (rearrangedMonomersSet.has(nextMonomer.id)) { continue; } - lastPosition = this.getNextPosition( + const positionAndDistance = this.getNextPositionAndDistance( lastPosition, monomerWidth, - heightMonomerWithBond, + maxVerticalDistance, canvasWidth, ); + lastPosition = positionAndDistance.lastPosition; + maxVerticalDistance = positionAndDistance.maxVerticalDistance; if ( (attachmentPointName === 'R2' && nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1') || @@ -950,20 +952,21 @@ export class DrawingEntitiesManager { const width = nucleotideSize.width; const heightWithBond = height + RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER; maxVerticalDistance = Math.max(maxVerticalDistance, heightWithBond); - + nucleotide.sugar.isMonomerInRnaChainRow = + maxVerticalDistance > heightWithBond; + nucleotide.phosphate.isMonomerInRnaChainRow = + maxVerticalDistance > heightWithBond; const oldSugarPosition = nucleotide.sugar.position; const newPositionOfModel = Coordinates.canvasToModel(lastPosition); - const phosphatePosition = Coordinates.canvasToModel( + const phosphatePositionOfModel = Coordinates.canvasToModel( new Vec2( lastPosition.x + (nucleotide.sugar.renderer?.width ?? 0) + 45, lastPosition.y, ), ); - const rnaBasePosition = Coordinates.canvasToModel( - new Vec2( - lastPosition.x, - lastPosition.y + (nucleotide.sugar.renderer?.height ?? 0) + 45, - ), + const rnaBasePosition = new Vec2( + lastPosition.x, + lastPosition.y + (nucleotide.sugar.renderer?.height ?? 0) + 45, ); this.addRnaOperations( @@ -975,18 +978,21 @@ export class DrawingEntitiesManager { this.addRnaOperations( command, nucleotide.phosphate?.position, - phosphatePosition, + phosphatePositionOfModel, nucleotide.phosphate, ); - this.addRnaOperations( - command, - nucleotide.rnaBase?.position, - rnaBasePosition, + rearrangedMonomersSet.add(nucleotide.sugar.id); + rearrangedMonomersSet.add(nucleotide.phosphate?.id); + // need to track the chain from rna base monomer + // TODO: would rna base chain contains other nucleotides? how to calculate the maxVerticalDistance? + const rearrangeBaseResult = this.reArrangeChainInRecursive( nucleotide.rnaBase, + rnaBasePosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, ); - Object.keys(nucleotide).forEach((key) => { - rearrangedMonomersSet.add(nucleotide[key].id); - }); + command.merge(rearrangeBaseResult.command); const polymerBond = nucleotide.phosphate?.attachmentPointsToBonds.R2; if (!polymerBond) { return { @@ -999,22 +1005,21 @@ export class DrawingEntitiesManager { polymerBond.secondMonomer === nucleotide.phosphate ? polymerBond.firstMonomer : polymerBond.secondMonomer; - if (!nextMonomer) { + if (!nextMonomer || rearrangedMonomersSet.has(nextMonomer.id)) { return { command, lastPosition, maxVerticalDistance, }; } - if (rearrangedMonomersSet.has(nextMonomer.id)) { - return command; - } - lastPosition = this.getNextPosition( + const positionAndDistance = this.getNextPositionAndDistance( lastPosition, width, - heightWithBond, + maxVerticalDistance, canvasWidth, ); + lastPosition = positionAndDistance.lastPosition; + maxVerticalDistance = positionAndDistance.maxVerticalDistance; const rearrangeResult = this.reArrangeChainInRecursive( nextMonomer, lastPosition, @@ -1124,8 +1129,6 @@ export class DrawingEntitiesManager { (potentialFirstMonomer, potentialFirstMonomerIndex) => { if ( potentialFirstMonomerIndex > monomerIndex && - // TODO: which case could cause this scenario? (current chain contains other first monomers) - // Do i need to inplement this for rna chains? currentMonomerChain.includes(potentialFirstMonomer) ) { isFirstMonomerInChain = false; @@ -1139,16 +1142,6 @@ export class DrawingEntitiesManager { return filteredFirstMonomersInChains; } - public getFirstRnaMonomersInChains() { - // TODO: is this alright for get the rna backbone monomer? - const firstMonomersInChains = Array.from(this.monomers.values()).filter( - (monomer) => - (monomer instanceof Sugar || monomer instanceof Phosphate) && - isMonomerBeginningOfChain(monomer, [Sugar, Phosphate]), - ); - return firstMonomersInChains; - } - public reArrangeChainInRecursive( monomer: BaseMonomer, lastPosition: Vec2, @@ -1175,7 +1168,7 @@ export class DrawingEntitiesManager { return { command, lastPosition, maxVerticalDistance }; } } - // TODO: if the first monomer is single sugar OR phosphate, snake-mode should still be applied to it + // if the first monomer is single sugar OR phosphate, snake-mode should still be applied to it rearrangeResult = this.reArrangeChain( monomer, lastPosition, @@ -1189,7 +1182,7 @@ export class DrawingEntitiesManager { return { command, lastPosition, maxVerticalDistance }; } - public getNextPosition( + public getNextPositionAndDistance( lastPosition: Vec2, width: number, height: number, @@ -1204,13 +1197,19 @@ export class DrawingEntitiesManager { canvasWidth; if (!isMonomerFitCanvas) { - return getFirstPosition(height, lastPosition); + return { + maxVerticalDistance: 0, + lastPosition: getFirstPosition(height, lastPosition), + }; } - return new Vec2({ - x: lastPosition.x + width + HORIZONTAL_DISTANCE_FROM_MONOMER, - y: lastPosition.y, - }); + return { + maxVerticalDistance: height, + lastPosition: new Vec2({ + x: lastPosition.x + width + HORIZONTAL_DISTANCE_FROM_MONOMER, + y: lastPosition.y, + }), + }; } public reArrangeMonomers(canvasWidth: number, firstMonomers: BaseMonomer[]) { @@ -1219,8 +1218,7 @@ export class DrawingEntitiesManager { y: MONOMER_START_Y_POSITION, }); const command = new Command(); - // TODO: bonds connecting RNA monomers to the monomers of peptides or CHEMs should remain straight--no snake mode - // peptide monomers, CHEMs could also be in the front + // bonds connecting RNA monomers to the monomers of peptides or CHEMs should remain straight--no snake mode firstMonomers.forEach((monomer) => { const rearrangeResult = this.reArrangeChainInRecursive( monomer, From 916d69eafe85c4a993b144b2c4fd7d371cad4dca Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Fri, 19 Jan 2024 17:12:56 +0800 Subject: [PATCH 03/18] #3869 revert changes --- .../render/renderers/PolymerBondRenderer.ts | 15 --------------- .../src/domain/entities/DrawingEntitiesManager.ts | 1 - 2 files changed, 16 deletions(-) diff --git a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts index c5fbc3d223..1b929f5eca 100644 --- a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts @@ -10,10 +10,6 @@ import { Chem } from 'domain/entities/Chem'; import { BaseMonomer } from 'domain/entities/BaseMonomer'; import { SnakeMode } from 'application/editor/modes/internal'; import { Coordinates } from 'application/editor/shared/coordinates'; -import { - getNextMonomerInChain, - getRnaBaseMonomerFromSugar, -} from 'domain/helpers/monomers'; const LINE_FROM_MONOMER_LENGTH = 15; const VERTICAL_LINE_LENGTH = 42; @@ -178,17 +174,6 @@ export class PolymerBondRenderer extends BaseRenderer { } private getMonomerHeight() { - const isRnaChain = - this.polymerBond.firstMonomer instanceof Sugar || - this.polymerBond.firstMonomer instanceof Phosphate; - - if (isRnaChain) { - const sugar = getNextMonomerInChain(this.polymerBond.firstMonomer); - return ( - (sugar?.renderer?.monomerSize?.height ?? 0) + - (getRnaBaseMonomerFromSugar(sugar)?.renderer?.monomerSize?.height ?? 0) - ); - } return this.polymerBond.firstMonomer.renderer?.monomerSize.height ?? 0; } diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 12fc92aade..1f4b648d88 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -70,7 +70,6 @@ type Nucleotide = { export class DrawingEntitiesManager { public monomers: Map = new Map(); public polymerBonds: Map = new Map(); - public nucleotides: RnaPresetAdditionParams[] = []; public micromoleculesHiddenEntities: Struct = new Struct(); get selectedEntities() { return this.allEntities.filter( From a8dbc3235ed13373a6dd9b6f3b2e97df1cb79c13 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Sun, 21 Jan 2024 18:03:39 +0800 Subject: [PATCH 04/18] #3869 fix snake line issue --- .../src/domain/entities/DrawingEntitiesManager.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 1f4b648d88..1881cfb449 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -951,10 +951,9 @@ export class DrawingEntitiesManager { const width = nucleotideSize.width; const heightWithBond = height + RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER; maxVerticalDistance = Math.max(maxVerticalDistance, heightWithBond); - nucleotide.sugar.isMonomerInRnaChainRow = - maxVerticalDistance > heightWithBond; - nucleotide.phosphate.isMonomerInRnaChainRow = - maxVerticalDistance > heightWithBond; + nucleotide.sugar.isMonomerInRnaChainRow = true; + nucleotide.phosphate.isMonomerInRnaChainRow = true; + nucleotide.phosphate.isMonomerInRnaChainRow = true; const oldSugarPosition = nucleotide.sugar.position; const newPositionOfModel = Coordinates.canvasToModel(lastPosition); const phosphatePositionOfModel = Coordinates.canvasToModel( From f705c8aac0bd729a96f77cbcd7212c2bc8619631 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Tue, 23 Jan 2024 17:26:39 +0800 Subject: [PATCH 05/18] #3869 fix screenshot --- ...bond-between-peptides-1-chromium-linux.png | Bin 13297 -> 13151 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-between-peptides-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-between-peptides-1-chromium-linux.png index d7042491641bef64028ee9ed87f6c2f2641de875..406484527192dbb6f48f45e8dd27d3dfdbe4bb5c 100644 GIT binary patch literal 13151 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 AT>t<8 literal 13297 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 Date: Wed, 24 Jan 2024 15:51:49 +0800 Subject: [PATCH 06/18] #3869 small fix and tests --- .../Polymer-Bond-Tool/snake-bond-tool.spec.ts | 186 +++++++++++++++++- ...arrange-for-RNA-chain-1-chromium-linux.png | Bin 0 -> 16067 bytes ...tween-RNA-nucleotides-1-chromium-linux.png | Bin 0 -> 15420 bytes ...-for-different-chains-1-chromium-linux.png | Bin 0 -> 25361 bytes ...-for-different-chains-2-chromium-linux.png | Bin 0 -> 23313 bytes ...-for-different-chains-3-chromium-linux.png | Bin 0 -> 22251 bytes .../tests/utils/canvas/helpers.ts | 11 ++ .../render/renderers/PolymerBondRenderer.ts | 25 +-- .../domain/entities/DrawingEntitiesManager.ts | 23 ++- 9 files changed, 216 insertions(+), 29 deletions(-) create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-RNA-chain-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-between-RNA-nucleotides-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-2-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-3-chromium-linux.png diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts index 26763e47ca..e0c5a70147 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts @@ -1,6 +1,7 @@ import { Page, test, expect } from '@playwright/test'; import { addMonomerToCanvas, + addRnaPresetOnCanvas, clickRedo, clickUndo, selectSingleBondTool, @@ -119,7 +120,7 @@ test.describe('Snake Bond Tool', () => { await takeEditorScreenshot(page); }); - test('Check snake mode arrange', async ({ page }) => { + test('Check snake mode arrange for peptides chain', async ({ page }) => { /* Test case: #3280 - Check snake mode Description: Snake bond tool @@ -269,4 +270,187 @@ test.describe('Snake Bond Tool', () => { await clickRedo(page); await expect(snakeModeButton).toHaveClass(/active/); }); + + test('Create snake bond between RNA nucleotides', async ({ page }) => { + await page.getByText('RNA').click(); + await selectSnakeBondTool(page); + + await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); + await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); + + await selectSingleBondTool(page); + + const phosphate1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(0); + + const phosphate2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(1); + + const sugar1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(1); + const sugar2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(2); + + await bondTwoMonomers(page, phosphate1, sugar1); + await bondTwoMonomers(page, phosphate2, sugar2); + + await takeEditorScreenshot(page); + }); + + test('Create snake bond for different chains', async ({ page }) => { + const peptide1 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 500, + 500, + 0, + ); + const peptide2 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 600, + 600, + 1, + ); + + const peptide3 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 650, + 650, + 2, + ); + + const peptide4 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 700, + 500, + 3, + ); + const peptide5 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 750, + 550, + 4, + ); + const peptide6 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 800, + 600, + 5, + ); + const peptide7 = await addMonomerToCanvas( + page, + MONOMER_NAME_TZA, + MONOMER_ALIAS_TZA, + 850, + 650, + 6, + ); + await page.getByText('RNA').click(); + await selectSnakeBondTool(page); + + await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); + await addRnaPresetOnCanvas(page, 'C_C_R_P', 300, 500); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 400, 300); + + await selectSingleBondTool(page); + + const phosphate1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(0); + const phosphate2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(1); + const phosphate3 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(2); + + const sugar1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(1); + const sugar2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(2); + + await bondTwoMonomers(page, phosphate1, sugar1); + await bondTwoMonomers(page, phosphate2, sugar2); + await bondTwoMonomers(page, phosphate3, peptide1); + + await page.locator('button[title=R1]').nth(1).click(); + await page.locator('button[title=Connect]').click(); + await bondTwoMonomers(page, peptide1, peptide2); + await bondTwoMonomers(page, peptide2, peptide3); + + await bondTwoMonomers(page, peptide4, peptide5); + await bondTwoMonomers(page, peptide5, peptide6); + await bondTwoMonomers(page, peptide6, peptide7); + + await takeEditorScreenshot(page); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); + }); + + test('Check snake mode arrange for RNA chain', async ({ page }) => { + await page.getByText('RNA').click(); + + await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); + await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); + await addRnaPresetOnCanvas(page, 'T_T_R_P', 800, 200); + await addRnaPresetOnCanvas(page, 'T_T_R_P', 100, 100); + + await selectSingleBondTool(page); + + const phosphate1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(0); + const phosphate2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(1); + const phosphate3 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(2); + const phosphate4 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(3); + const sugar1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(1); + const sugar2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(2); + const sugar3 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(3); + const sugar4 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(4); + + await bondTwoMonomers(page, phosphate1, sugar1); + await bondTwoMonomers(page, phosphate2, sugar2); + await bondTwoMonomers(page, phosphate3, sugar3); + await bondTwoMonomers(page, phosphate4, sugar4); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); + }); }); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-RNA-chain-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-RNA-chain-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..35b38b190c26ee8792d22bf72a9d9c2afb9f218f GIT binary patch literal 16067 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 literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-between-RNA-nucleotides-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-between-RNA-nucleotides-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..12edb8f5d12109330e5e62c0e361f10e22f8d2bf GIT binary patch literal 15420 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 YdNBJj{CA!s2>g)IMYG?E&%50FUqIEqAOHXW literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..f940b79fd30b936aeb5146f2c768a02ed92e9e9c GIT binary patch literal 25361 zcmeEubzIb4x9>=ags31$D;*NjT}pR%2m&JA9TrF{A<`w?IW&Vv3rHhFN)9Ooga3c_!6Q2#$QS;PPNS5bL_3~wJxOUR5|4CW zvs}*!lW*$o`@Y~QZlE&avN^Uox>p&n|!*l~t9LwFXa=|>NbGI=h zPN_TGvq$l^JmNXC=wlAvJym%P0T#x4@!x1$Q^FML@%#6(;;mLuE^BWI4-Zcb=f?hd z(nkkBi=H$;t{0aa+IW%dDYs6clrOg|C+Qs=Fg=?lgkt zOo|u|L3EnK!}sr&c=4F~#5L7NxpiPN`@d9ISonyr`LX-kxOaP!4j-S$qg~tG1)kei z;K;J+aRaoazFT)=??>Mw*J@2nbbGER;+M*8h8>cpJ+f^SVt#)e_7 zj^KT>IDxl@Z(s3zgO zb;1L$DNV)u>01};{sh8`jWh=!ZyY}w6r%(#oKdJIHy4PMCsWGfeRS5T8O?u;zdo{W z6>a0&oHHWRLMk`ud0NANN7rL zc3ogr67utpH0fU+t7#C@JojICSAP}~8#NZ&=zGwysuS(&`)DeA^96s|r+b(t@Nt6B z0B=JRUQv`gei+JKM~_HXNzMxtvY%}c7q7F=qnaDDccLMRov7Ci^Gu|&7;T!J*%N~H z+9X=}5P>!r6xL3PKivnLiUYka@5{$9+Uz(P)I1L$zKb#YGpLfX47B+HK6=Pm-f|Cs z2IXX9T5pbS=N&ZT8`fAj$u)+=7&Jmn`O^d@4)mDb0L#mjeE+rqQEN*}~+PKKD?95xq8i zV}4(K#(RZ1w@c!#_pjng_;@lEtz)7+`4Sa*?Be91mMwTO?&fwIrh?>z2Xj1+sPtvb z+dU6Q{%d`pg~2fK_J`Yhx2NrVBHrwJIK=4oZX5%Ph8bY6n|+C0OQ=Nc7!^KReEg&| zl%?NzHjftU?b~_el;ja8r{DQ++wCbH4NN-xtH^ z(TZ1o35kiluM<>G8!j%}-Z7*fU!u>BPdym1TuslWr#5^%akyh`6wt~Cx}5LFHX<4& zLy(PsGBfblV6l61s< zOnUXSR+TaK$Q};*fwkSKW6E!&j!EOq?q+zXH;&zjJ!Idyec}UBt zr8I4aFy06vA}zoslCGd2b9TZXp8#*|ylQ~#xU0+j37cNI#QsXZrmt_KRezE;3`BYm zGg>qf%)^-tg7f{on}WW+0__Mlb+qH2*5dJZo=wiNZpzv@r427L%a9Z*tDd1Qs;bdC zrA7tuth(z*aL0-Jx<;7#Hik7nwmPgtH!FI zta-1OwP7{Qx7zR2Mf7wj)}Zo5Xs&Xy4on`nBr{wfdCiq*UAqk;##3#vV9Sx@|$%oUfgNXg~tEPax*mS0Qp+qm$ zfFdT}xH~N*PwT_iS*l#)szqqazux~-!^_KysD(SAR3;=OHCG31lf?sD=xmTjTP=3fp!4N$VC*hg_cd}_t(}#f3OAOXvH1P+*e+&!jSCv{ z(>mQ~Pq{^?9IfUh){;9ut|PDE=vd~61WhHp!G3B_Ib#^1B}&n>eqN0Zfn+S*tqZal zbB`hC5|v)4%ltHf+K5D?U?Z*wL`~ObD@ChwI>6OkD7yaon1^U2Oqj}=U!A@m5S`-6 z%9wyrA!d-*xN(p!_vPAtPEncJ=~_}3Be4?j0}QW)5K}>Vk&fBG#wTpIsF=zdwPS-G zVX&*wP;`9~w#h|2>FiJCiS>0vEin=3=MLjIjkS3Zc>W`_#-M)sE@;q;3x0TDJ!Mo- z3w&L+F8rbOnbC+Q_yq!bdPUI{FYKD8rElRAM_W|<34EsrQKbhzaz^hcpl1lKBvQ3` zb`AC>QDtVNsOfDNV`|X7@`-yI{%m=`;2|RspXe>{^21OV{<~1ZO@e7b%`F@wd7x#N z)ifIIu_UVH5}@b-QE8RxZwGYXRhSrt14K(#p+d-)mS1Pp#=JSTY%o--8yqcy6~rUi zn~OX=eW|W7DcH`aRT-9=$NG*OP)Vk08ASg<4a+66&u^3!#N=S(ve#Y>y-DWei^6bxx&drXAW9pg#vQ@6O5wupH@lX_iL~) zJ32;J?y`GdG`mz<;06xj_Y{QplsLw5XR71K`jMf|tv>{>$tAi5f2E(4f8Vb$esJ#+IyYT4R5FxC00LTXa{QvmbtKjJgrDG-zCrv{Mof8bhRMQzRHD;Ah z67{WJkO$AyUSS(SEG=gm++)BO2&C!$YupUGgX80kOXN-h9h*UQ_a7ecoQW5MJ*aXw zzRXYB*x0yXDMpdU|IBS<5&V?#9jHKIHciy`;5~<*q^kHu^($N3L;k>h{#;pb>`UCj zNd~KPJGZgXaATruB8k`5?Rdu1*33+z%Bp`jhF+1!eO+s05tvy9#@#v?)5W%D>j?Lt zNVYw^)&?A9VO@*4vN&<9Wlb8?7i+T0(cn!K+CY=N6W!&$7|H)?tWY~w_EubOE(4|K zv~v=_W7_OdE!1Y^N8(=zLTQ~|w@+5v#EKo)4;EBaX%aFh{p=tyEd~che-f|a;o)I! z7jTS_a%waZfp;&s3O34GO;S@+UpYEXkhGpi^YZX~p+Y%5*rPjjut$%L8?-1XDTTJG zN8C0_ph;9WQ9s=+SGwbLr%0z{xcPXtXllw}#%)A7w+pp>IB_u8o$i2Hr_&+6;c_fh zz5ow1lt5pScJNx|7@ojOzxG)04Dx^tNbtdEo?WjTc5RFh8Q}bHn>#tF4R;$9qh9Gn zM|pi9EZV>Ll$tz%F!=)kea;ZphvJuANTp~rq8W*A>Ymf;O>^oDwmwPd?~MvF2Q)33 z^VSsx4+KDWop)W}P}^uQ;`BZ`#qOS$t$_Wu#$ zF?@AXFnOh?(0a+59RKZZ4}Ro1w*fu0R8qxQDNH9RjRFFRKzkkjl(TOf42L-!GsP>p#LcytPy5-P@banraaPDEPctPPX6wsZUuTOh?+-l|J{wzneqp06 zXWGJ0a9X9f=~gA*^R7~~ap`dLbIjY2z&SSs4Fxi)7%XJm))s}guY2lruoVhkelUhW z6h3ova>Am|ob@}RVL3$)IHpsGpJ`N6>k;{uQA(16#ev>NRu<~xi^NyLjF>eY4=(;- zDBtTdtQtr;l%#y41pc~?t4u6!voisg8X6O~rs=WR*V}Z~G&*N^vV{%_a;A0q1a0rI zABc)_aQEC|`>h3AJH!_{>ud!(Lfy%W*g^yC}{K0aBJk7<4eKqYj@STFk*!sMhmtJri?5^#O8q zvpMc~mqdz8X^LbAiATT;nt1zqB&I!^O*8H-_77OPp$#?)HX6wymq^NZZlrK05mfLQ zyMp{&5bfY^*)95*D3h5NHuJX$B8{RpyZmbxd3iXwMw~vD;@^a1xPc88we~eu<)=Jj zYWdD!eO>>H&Om09t|NBKsx09d_^!gr%&7ZLD<}ySaLVlJdUdw6* z7l+dS-o`2#MD0aNTgMk78V6U8?KK@$RmeITeSfE~z8aExIQu#WuuTn?@ujJ^<89v>OnTJp8h&?~G}EfBO^eyjhc1 z!svvBPsHxV#;3ERFDQ()0XA{I(X>@nhv~yO&7;-dw zHz!~CguUt6p4OT|VLi1KY@_66IFkz~VSpYTVDwnA^wcQJ zxbt}SXGYUf2I2|Mfa2|5^2#0e8xS=d>}iN19z%_{tM|1kFhb(39bJ!HhyhU`ey8q6 ze7Iqm-;@V67!ezHaCXJ(*7z9~1V-?D1U=)VSJ1(=!J~^_^_7DSrznoovk4P+Nfe6FRvDQ@#^cp&Nk<+6{Kw>Fg68Xf~ZG}`JhudfK7s+92x(dSEuQq8aDz zprQCUw{IX2YNh0`@1CwAu)YDpV{8_*3G)Ii8F;M+@z&!BQ=R5~N?{?l(`9Nc z*)F~r|6^4kgq3o7fR_3ZN2F1yk+yzju%7+UQRr_uhS-MfhK8_sGk`xqytD)F(Mc6JzZJR}DGLPd;1cH1_Z;%BGEI?oo?~f!6(A9%vGmcCdsA%tS~r-R(8;Q`k1R? zKQvBblzYBerCQL~2u@Vky_S#QzU`GUYLiz}l$9kFEwULn&&NAa_3UGZ z%j-t7HZ%|z-YON z+Z$%)gd3yNO4CzzPEJem4a&;OK#B@MLWW*)GJvI@E6;DTK_CGOcn(2C8!pS{Vammt zhU9aP(P~}Rw~(1w35@8Fd1{pV2{ZalT%NAUEtv+eyiA*ygPck~#)t(#)of_|L3SU& z&)89FaCO;$Jg(;>wl^RdM1b4Y9{8j zkor;p=yUVBli_?%T}~@;AwlUU3gk}9MD^ddK_Sq~V znuI#(3Z5AmTojL)gSfGNe zFAOT>;!dkdHLOnb@}F?tuUsSlv?aEb^;2JgC)CxT{YtNyjw8nw%3ZKdm@?rT6Dw%?eEPxOwC>*%D z(B6W!uG4H1Kp+%%Ux%yj(}MMi3nPpgSc`GptWPQrxW*yggSqc0<&_GlRWz+hVzi5-Vo~1yT9k_gzp@#u^*}!;yz$w<9`^1v$e@S zI8tvPndWddCr>Fp(xO<}Rh$VNo)vR^9Mlu=0uI-_z#{h5x)2D+UC5J`rCD*sSyA{M zjl@Fd1JIg!VN`nJSgNVYOAu~vU-^GO5U|*ru+BReI?mJTSm(JJrqyke@>Ok-?tha5 zWSa;bh9?yt|+<-o$ipe0WtI9b$$Lg3lOLVB<{g+V_X^ z*i{ipSBc{*lu@OGyh5BkTb`68 zpMqSIde?&@Ptlw~(<|xb{nVY&iPp-w`p-w^CCkSIX|G+5dCo&NRb>rPGZ7K$o`U{^0JJeS8{hd}uLs}}$4@%3jg(C$YN zH`__fqe0LjE#Lg*Tv22GOK^(6!Q8ruF*Jf;~D2DHGqHqD{?1DqEGY% z%e~MCD2`gn_AM+?^Q$(iJC9A ztO4Dy`0@W(F-SzaV<58JYA`Ja#A;g2&CYD5m)!j+-f;}dNp6$TMTLdq`a43hiN$#z zH;8NuC{$SDW4?1qqLvbd8RRUm7~!FuE~dQTr1wcqFH=pflw4@D>noSO|Aw%*nk}5} z@PJ-hlT=;1V?i8cP1&;ZXfS~viQI-U2W3}2c^*64!yr)18Xy1sv?Y*lqrj0fXS|kw z;LmNmoTUa0>37{AJHUiN#f1s+KIxXdOc2}q)ZueDRx?%SJR&*An0z=Y%vo$V?%UV8 zL9WD{*n1+%05-rwz#nnSBr3@mLLFv~S65c7D1A4dfHsSUv&T-($xoL69wEX4>u#|m z5VhTcG{MKm-|{tNiPzB99=ox_pM-)C{YCltoTA{(Zo=y~8%ja?1Eet0)o4Eb94~=a zdu$2y1CnYE`J#%<9R<;>@CXPL%@ZF2`-45rg_uzgv-?F;`TgNPyF3oe2mDQH;HCE~ z8=KEO_n@K|PxoZzYLN%{xnEyViD)a;y8}a!I0ekR8O8egy4x?y!2QqARYIts|668n zZ4FC+z5ttp%dUu%Ie{Er^?6K$z)0i7L95P3 zv4^AZ1g*Q*&<7;6{?t7qg>-g<(Vgl+C$LOl&zx8ci+p+FpN7r2?45wRf`&m>4#pHO zHNAp&JBL@`8A{um(ZF8RnR4p-NtN!^zvmPYc^n#|bOU0B4u*-!AVLAue(F99@Pq(7 zxt$$%4OxNoZNS`|unUxQe32oFLJqDj1gV9kOCv(yOk^Jb14#mN>p&_Ze{3Z?GXS`T zK?zpNF(%xw=ZR?Vm%H`A7j*+Ba#B^W3xHf5qN-y-$Eid-EQKdFN$8^_6q7O5R~6E5`^y>lFvi`*xq>`c-C%+Z*t?^VYM2 z8tQ%f*6S6+#vxY1xT9C#rnCF{`KiDD-UVwwXU_y#*5ZeO z2TSQ`KL;pC37c9!S`!j-t*8lB|N+^nQm=aLT^~L?mPUx7>$^& zn#+w<5!B{rtyZ|WxM|2p1@mN2+Kg?v^lLq^yA}?%%5)oJGy;sN4X%#kYyyP8_K5)-1&zUA}bz&hzQt@ z7U~swL0NWG9_LL2*a~l%x8d0WyjZp#nMxBxvZ7(~XC! z0e?H;^Z}g^1yQ2{e!#fm1CcQ`y00e#>5Kx+&{&=UxjINf|I7irMh<+Dn%OCcT?~x? zJim9n#X$}h;>Vc=8ijK}Zv&TwGA4)^sp8)Wp`0L0HaipqqJY%q1iSaouLTe;15;%J z*=$JIyxHH;iF5!l4FdL05MifK;KKg9v%LJ;TY3NuKwk5rycP;569X0e_boLF;^G7y53z#IP(c&Bvg> zzaOL<6mYt3LcsQbsL5bqVO6`XssQ@q3l%1lAO$r96=?O!X==t2vx}&9Q3p05)PrK$ zcW1)x*Q(js zF|WqGa%DhN<&#_v*3H<(sbE@Wid)S078F?&o@PcxOU<7^)a?8K(G{0dVkpGR$r(4n zN1O(g!yPmPZmG$}+60~?R3h!}uI+7)&J-s_LH+*w?u`sRY@>|tcytu*U6dV2O3TXJ zJVCYYc(Qd7-f`c;QXXF&NZUBnv;1p|cfwanO5;L7pF*RFC!#oLQH$sjAMe&l+*(r= zFz_*b#%hYqJZnm2dcI*Rn(FQ%GtnfTGsR+l{1N0BLDI745vWYd30cmOxn!2dkzIb4 zrQx-dpsCIb&D1xk9^Ra$cUT<|&6V{ES7Imv+@FB~nNswdpv4o&ofn|+WpdwEs=-oU z%eZ;@Zmr;MfNZOeNU?Yc4x(>@jyKRFG}VERIZ>_FI-x0TM#JULpB-TlI>(bpZnm_q zc3rj_+L6=2#Pt=#=Eur_q>NXwR*H63n=y9oFt3?*#I_I+11DzsbI8+wW+KR*h$@&g z_)z+6>*N|zM}^ZFpm#~X%#Tm zki?GVs)>gjERC0gppNc}lHn|V<_`%fO)+bheuZRx68cQTcTwyd(smQ9W3H?O%*pRM zX}~#OyR5zynlK>>&92Dq8zb1R;g}}qgxBc*su@(g*!{iJ)T#@<_Q7j%PLO;rLB0iX zSH|8;pk#KI=KLqR7bVyk5f7bS(}3EzIdSWqoF)R1yW{g8{ddzAExCIg0xXwI4BLUC zSQ=07d;c2t%TRi>6-mI9s00eNl!QDFyZ61m37mI&Z%k9*x zrSZ$12`Oql7#yiCS z^#=a;c>lxG-_y3jI@eWivr|Zy#zqCtU$L~mMw)dCw5ARols^E{Q+$A7hW)rsRcx>~ ziq&}iiU5UMpqg?do5H|H?^lVff4$LZ>Q#*fulQwrK#Mc71?s<_b69w~TXvA1ER56A zdXY0i>h4ZjH&`F!vGusM%JzY1RP;GeF%wT?3od4_ME5M*u_S(`Nk$>AZA6~%Vz0Jo z9lqk|b9o=%GR!ykC9rD!P{y>@pA)R9zwgcPT5<7;$6*(sQ8Z}u==wDMKTF}xNmq-a(@L+da@?olAF!O% z66B_Q78Q(HSg7{#*=&*}qx}!fe{GQ~fhtaay!J(Z0`)2X7iY%!KHUR^16R32N&k?a39LYLisTxHG z(2C8%#y9MLCCXAd5D_u0YK{&3S!3p?amjgL|M`93MNF*Q@9#IONB zQl6^Hi?&pM+`0RSI*I^t9ST9NC0iV#evWWApzN0tXaUjrFOp{W}oU`DvVZ>0O6LR-x>i8p}qoa4q;jLkVFYWC%herp=ROpuP7SSOx zAm+Gj{`-4q%-3xP-*M9KYjKKrQSwa(SK`}Sh>1T=7+WcBnb7Z8wl1V@$iU8=^;^{ov&5D;pG=L4b z_)XIKbKVS*b}IGU`<29WfpA(D9>w>io>=$8 zG2M+Q;q9OO{By<0jxE0qSE6Upo;)-s z$f^|h(vNh5ZH)|OXz~Q?$i#wOs?C4~W5 zq8dvPbanrBi%~wNu*lXAzT>qyIg}$PtI8{irGVYlMGg*|2+Y^G6jA~d2S9*M4s(@l{{JZG+IdMPSz1)zT#s`75RFTwV7Z~4@|`X4ziEQ*}}OOA`! zuhBZyU8fCN-};ZbOJwyI73+foMO!*~W&F!a*b6T+iPhEJIS%4*o3=NYsJfFWIGh(~ zq-lkejEt{kv!_e^l9@hMehaZZ9({Rn8^EQqq$Goxy~x1P5!EYsU1RT>T6=gQAb?t{ z&Dug6HiudLQ&;21Hry}p(?LP!U?R6{7lmuYN`G=5D2b_h9Dp72cJaiksC32|jRckt zDoE}=qq*yUHj+M`lVDOPOXdAcRrD~9&vCZ6*;nzZje4&65+=?O_^}F_Gyk6oKHEa0 ziu3YhS#?WCd*fN%kz3G>FxJwaA>!xH-?uL#Etf8?_PH#%Nd3>R{PaL}iMrJ#92EDs z4+yT>EO?W=+@4-Mn6!vqUyu#RP8AkXiuQemD)Bix+&F}x6Re?%NAdZmGd!CXDRaA| z5-YbrkVLVJOueP{B9>8g{HFMcr2n6{)IV&6IhxkjtL9jKs>yzAya}bDN%d`Tb7(wx z>r3CNYpmDgRZ(idt#HTK>%LTk{ zYy~w|Gahhzl&G?@A=`C}QO@>xg$+{f?qitAwvT`Bnp`Z#a45vA3>s$mURu;|pZ$s+ z8>=w{^d2Q8{4kq(CX>FbHF|D}ftT3LmoeS1GT@}0y0ElVMf~b?um+TJy>XzvBo`F> z;rFff;sj#Gk4A$1VS9o)STHc^m!N`yb_wE^-{Ldet9K*hj!o)gV`B}-?Zz%jwGw-) z&$CmF{H3p72gnasf`J_UH^|S%p)Hvp8+-6;&`%Ojo~)5;)CF5>DSQI zESQ@57NYc+c;s**diq1_i=KP*_b%B4(F3b%m3b=X9s-4IE`!S`CxMF?LH;t^Z8g4a zX9UJ6!(-t%o&}B-+iiypLUA*-0~7vVeyfPf41E7Kw~E|y3^ZibDgOEGJuawe^0zU9 zPu3L4`Zg$DW!eWMx`I+2KR=)2n__=%xO;fK>WQKEnP{9{h6l`pb1X2L0CKc|hhn@6 z63u)tuC$Q*Q!9h%9P(2w{>VD$(C~1E8q*ikDDw)TxmIt}av*TiZeLhxcTw$DgWdM zJT;vvU*LT&^(fV)SKen;c<#B+V~FJ&KpmA+qY9BJEx}C$XT#hc=4@n`GF!NYQcaC^ zVL=5_e*KTET2wTNiI>XTw{O9A5zj&~=z*8}EF~rvVTd6}Tgi}myKju|%E{rn#K*!Rsj#==S6!7#zgvjZFCY>TaK-uebP zo(fh*%H%2OJ;>gefPC2JUCXcWW3*+Nc=e?g%Q;^_Gb!wEyXv~Sd1_2w+u9^A)^!Q; zTU$-R-pN|Hbt4YN&fNay{5S7vF+DBM?Qcky|6qN?R!jYPo8@n$jZI|y;oL0+**j6u zx~9fOfk-H|&9`^A8rBP0K~W#R%FT=vRAh{;QY=02T?bqiNhGw5*EGFUMWpi74;^4* z5=I8!4`Y7PT1J28q^Z_VR-?OK{3YdPPzT@ulm+z%cigd zM^=;4vK|%|vS{&V0{DV?_bacGIt3p!wW`SO%~a=3gbRf(NMRfvb;iq0wu;;f`Zh0X z4lqR2VlSvZ21rWbDSB>~U{fzyJvTTJDWu0Oa%-|R%C$McFxNeX6`PwV5x86P*r zk@1NRv`J^VShIa3tlSv!5unh}bZrKxTRED`p~PN959hLc_XInnyL`Q!rowU}St75BeY#fhx0-*>N zov65Bnbn{XHuj6WzCuWqaAV8QU*)S5NHc?rTVJRwsq;Y2IVH9@(hzZIsov}4ovPNY z?W#yR(;8W+Roc}xKOZEu(0;{P?YLtm-%&!hwYH|gXS+HffMUeVVE-;L{hw>oZLjk7 zZdukn#_2=L)a%_nsXJcvL`>P1je!)(?Nc#fPpY%I#F(BJV`JJa3GdJ)&8|G9C2lqB zeT&QGfqRnfEUgrmHgSUenB`=U*O%%WmdN;c0;KhQ!%|k5JLaI0%hit+q@|zX?B2x@oT{~tt#z0wR0WqdZbnX*&g{lCZ#FctmTL8GQ?H;c11c8p!@HafvA7u9 zp&rV=b?*;n9M=A=?EPb5*d1=qKQZsL)#GGl)se^b zZ*rh{uO80pT57*XJYeilu|yv*%RBwTSz!WV#G&t@gduG8iAp+KTTkBJk{y55R@4Vl zDd3LOkCdb_Q=^5HImlJVebWAyl`D>L-2VGf-Q51QBG&%JoYKdt;d0)&gP&RLTCKPC zdTtMr1-DCLq7C>nkd0gBo#q!52s-rG+eebA2v)wRRQ1Qwb;ok@BQkmWjY=g zWp=jU>hO%>t%E-{qB@9Y#PYs$Mu-}@4W_alze8wPMqIYe*c-4Ih3nhn_wtU8=3EWxWeMNm~pYo}PX#gckHX?q~nI zAYOkv4V8_nOjYsIdR5h{UX$>5=cmgyGe;fOb$W-7#9EDb@%Kh~~k-W#~a6v%_YIXGEZ;GTAMx0)+h#)LJ(AHzZ$y0*4MmleQDhK7@oJo5zA>rShRcVE#1Mdop z+Rw=$dKj_TkaGHjzMQ>1E+C#_<%r)4E`4{m@5)^QY$YLCWa7_@5f32WS$YA5%enRu z{U}bE!S@#*b~$$VhB+wD{aXuwgW`iD);1KG6W4etX*njr3s`?2zO>oqp?u_sg~b&n z6Ps%Rp^paQL4vZvyBgvZa+JHei)zR7v2JeF>k-cr5rJeJgh-p6KYx5YAMwCDp%1^X z|MeV+8RI{Gk@Z#jWp{bx2aPE${W^?@Ks=D>$pS1jB;zIcOGub77hJ&2Bu19u;ZNSj zL=n%@i|_1T%M8!Vbk#}*0X?GzkT!KxnCTH4c@p-<{w;)?36-~J3e#ZmM@J{^$eKY( z8FDSh+lPM92UQ zF)>^#0EZ!UAir+`ju!bfr+&l@BjbgaGU@_Akn4RH!;B&le+5tz*WPlxL(X4Nu^aJ* z(wE1_=WJ|brYuaY9>El}s1C9d5Vbq+XNlL=i%QjLNOi5PLu&1Q73b#KBnj^O$!l=x zsh2ONg?;{fn^&3AQ3z|^>+dw5WkN9<7Ng1(V?4I~jKS5w@sw!OV#fg2(@)3Z{>$`X zT^3z_1FnM(pW$2M{zcp41F2HeYff^<~oVj*E5=zGd=%y&$3E?=CUSv*`>aEFKrCxy;Q^RFieBG`KlzoEeiWz zmHNphK9V5@Ny=TAA8%gIYRTB!JF&O7sk7|2*ul@^!?O+HgXQFwtkZo^*y_?aeYTB$ z%=}62W$zM$e8}-STXoV@;TvjnCU-kRkaP)p^U|)E*XO)HnIAEfUOIu|G~o7u{!52Q z-MMVJuLjAc0m`0p&4o<*eqzyuMfIYjOgyF6(|(91+4^lEBc^9Ii&~f}+Ge?#l}>&& zRrsm6@7@#n;cu9_%*p+Q^{4*!ljS;as3V&~TCg*(wBT*E^}ojP9$?hQG1Ag>jDa9t{(D28sG> zIF8Q-_Y=6&r4yyn)}|Zg5n?6LRe~C3j3xYDF`8o>|53__W$k{k>%QG zTv$}bM~TkF{MV4CzdU&qA0IzH;tUusmqugM26_K?8*?_>t35gOqmrh1H1Z@UM$@2G z1|0(Nj#bDx2sgDG7T#%Mjqb|E*P>k1H%HI;@CJwGbkET%4I{ z;K(?~Pnn$|l^IlP=P$3Bt2FLD!KU+=cmh=JmdeKtjDo@tr7m=eNJEg;hB5zw?udd* zpVBy3Z^?u`ime7jRBsYc@lfItukL$;N+=s48ObqzE!*wsa9-;HJMU(bQ$G`L5vuwb zs*xc`*CJ|53($v?T;;rJoBt#Zt*u4H##n@H?5}LQn25J@_>#FP>33+xp2x>~kB#z3 z$5cDa_|!l>Umk7ZYMYu`3sBDc8MR@Wd5?{SK=sx(H+fPpsQC^&xeh$v4d1&Rvb^gx z3Wpb2r+KT)%*-^*ztPXNXv3OzNLZ(=v;XNdH^Bz=(}zyG#Cq(^X8R*&x#RGdD8VXy zo)`sbdY{!)Pdvu9kgZ=;vN1gNQ#|eRX1&`pz6XEW$+h(L3vv|8boKQU5pw0Bg-;%x zUH})kS6C`W0}cQ?z9RISw<)~+HzzBEkei4psAGDYn}iM6^W{wint2K_N82;D0=LBM z)^^^#F--ETvJ-4M@>ZijxeuID4H(W1|IJ(m%U}a90PD=#UuL-tyH#{17z4z$sXU@XT&d%KC zVUl3>y1){ie7VDfe_nV$XqlIfZ@rV;adfK27H|eEB?dLUZgg@6^)5N!2JgXGSwOr! zhk_bIth%pnNSgOby@g4-C=!j$s1ByaGO6zG|E%X-bD%fr?VI)VbJG%x2wisMrh=dLJT-a*9Ar)6wh679d4LKtAeIX|qOaC2#ZQfol8Ma~AdYvXXe$n>I+ znB6Gf^y+NF2VBEDK+avIiMrqx*VgKwbTc4&Yy?gP)mR2)F3MZP!#+%}gucnXs1gLh zkhU&=Cy?oDVIhvY$9GiNA}eU4dU1ZMd4IqG(1t5@ws$$HC7i**mOP2_FwPx$M0i;D z@vwMZSG;@GC!-9&>6&FwO)Kt+WlWB`5!W;@ z@a{UQXjS5->0@h-w=2gIIwbn+%}so|nk_ z*47xHmh-l^9gLmYil2**$J^?9|E8*Uq4xjWGf}0|GMX#Zg{g)%1ve+7px~igd>7Lr zc1UVcPn@keXLfOauYDm1oTOxAQKl}51TZ`tb~D;W&z+%m0!KAV%bd^b%_f$X)W(y) zpDlZQD6>xWyHF+JVu6H^KagW3Q%(X}NJ`$SaZ)eX_Yox%9-kTv4k&*|po{8@0`x`L z=&>~pNb(vtgnPsJ-f4TOi7ywbr(|g@C`Fh%ONDrU7YUySEXN!d-q9#-Y&bmePv%W zTgyn>W99nFHoTxk%v=aZMZ?lkZ79REnb=3h&B$Ww)^SuxQPD&~i`!clLEm`k6?7G; zHcUGh2{p^T{nNyT{bmi_%P|?s9`dmmyYLR(9GgVgziK z!d=47q^Q@iOD^?VCYM8)_e(yULW*Bo1MT%%*Hix9(C08+C-Fx5KvI?giuj=fPy{h1 zW}6>mTmnd%e`nbPo1O&bbatkpz~BR50dB3dWXlukAa~RPFu$m$lI(r3xZI#fqU`D0nM-I7?nS$^#w#R8ebTiHf8+OD3}Tx(kH)9|!$tUA z3@)q`1mScE{)kcAMIT?Ci{ zaB+Gm!pO7=7vb*{RVFPh>Eyy<5bpnoHvDk8fhb8pl=t;jJ3Z85>j5Er3c5s+Gn!3qNnawmwjG5g5 z6eHb+`M5jmuXy-5ZW_XzAJrdE*#p7e0l~t7U=i_sTXz)L=j|$9Lb0$EY@HLw$Jv)% zz~nyx)ztuhgzIeWVc2r5odF&Jf&6iuRdK_U=irT4l}uGR zLODciau`v_c?gp;sgMZed`@LMXN;Ur2|0v{m@w!h=Nd)`qlk<{jq?mnW4@~%9Vkw^w5&L3s=h|R(efXR+?A7||sIH11u>yv0>u#0lS8O6| zykE~HF6?n)|s;b$|M{9H?+(Gb^>na);|PM-3F+dG9Yao(T%lSsAmtjL@of?>#}Wwwe`xe9B_EW|@2q$NSZ#5>|r zw01$@w-oGBzx55*PZhR-P}^<1Mgx%WNeoSkcBEvU{9*uiB5J--b*-fk4Ir7$HamOh zr;MAqrDb7E%zX>ixZd0VE#twcX91tEY94UY7N@Rul5lSo1>}u&g0lGi&*Mx>s%h>K zX}iZJOd#E4@p5R{vp1`}Rvtm?&lnS5KP^Qyj${NFUFyc_r2^m8l-Lu0meOPq*r`@Bw78k6| ze>yb_Z-nLoX6$U`IVn;l$19DIjFd<@O03jOwbo^PD~n2{u`(+S9&~)ei5g}I^+ix@ zEb%PbZ?r-?vu?!;gU?QDsT>=-tj?q*BGZKW{_hp_^Q5>xPHAss*+`4IP9%@MduIiO z{P_(Ns(UjPZ;%SqZ7WaToTR?^%w)WuS*;}M`1mXbGFTg$JbbgCaBh_n{(`wZ1=MRE zO>a#8y_y7~#Wt-8eb#sOOR0eN8_p(Ljl11do?%V)#UkYam;;LF!kJ3eiMhdg{Ts~rTJDZL+t>E;a%(fs;15nl(!!85e5omvq0`kkxz~2J zhE<#>GgNfl7elG@@zzLGyW_oc!uaOm7ju&y0KB(F$|^kKRC7qGYJZ>8%xW0FleT-3 zs~?-e&nsjWhdWUElZrL&?p@ARKN~bU_wl(*?KSEnUiV=C1m z=7OiKbSjm4gj+pTaGd66L~yVM00Cw7%spm>E7bv$ZYZ^>V@Dd~(7Ei{#A+*r73 zm~NVtEfn6{BGn$QH9+&d(k?X?TvOvD5bFz-tLX_iza(lE44RQqbRLJ~#;&aJb>)QQ zQ)gy&6-T1*uY%8$WWoqq(0#;IQcxj_SLhEcxYeh@3O0#TFX`}U)$-aGL{UhxVL6&YHlW1&(9 z2O-$f8-7+PlgT{tqqx_Vdkg0Un!{P6>_mUn{E7-`wUvQ!M$7Kd$1Fyr;_{GNQ-4nw zv-%6ZnMT_s?ORQ(#T$>C;e#I-ZgJqC+ z)bF4<5PxB+;HC1z&o`Rp-sjd{A1rb>nMb%O^VjdcDM`R$lkC*PdP~%DWc@66R61z( z=XdqVn!7tI&E)r!6GNAr)L0uk8J*68k1IUN^Y2uh5bKWmJZGVF5WQe;nQj~!M!4OQ z*Me`3_JXKM>4Z&N;qaFGd^ciEt*r|a66#=n<-{)qM@0|vxwYYBbaC5wcp!)c6n)&c z+Nloc@0=rL1Fsla$|53=Hj~oHBbk`X+q})-0ldNR-K8Z@OeOoD7#wp`Zhs6#%?bXR z!46@WK*AcY$-b5Ug@Acp?3^s9OWVCG3V5WAe$%dk)ut`^mehXaj)s-h>)SC zFqW6`SCygh2aQjvpC74UhpgHWbaCNHE)i`croNA?j`|)lm$X~pnfdYkPXsFbYazHuS{?@X>H5V62?`OTe{rkyde*&=C zv1p>&$s@`uJtkCaimb$iLpFbyo&2td8W$Sh?`FKV;UsGMq$e!Y>v#TdI*6E(S+j4W zt{U5;s-nXrXJ`>oT6UZGI~NA3tR-d%e51sIPbe4GtL<1-SH{0PH&LkHJF@?kqD z?LagZB|Ek((|s%M_IIk@@$Bxj1kM9a=rK`*Jsxv`h7Z}dGr(bBbyoaIK;*V1I*jS#GbvEnzmnZ~zZ3FBLiYW(2tE*dV z%4|x83m)!#3DC!v%j~&|!(46oC@Ysm*+8@TA$acB(+IYKvY88q0Eq;CEbi;?SDp=G z5xtW4ALtPuc&bxSTx_p4vRS%41uPirh)&yG{Oc~_OMrgted71D)hVl}R6|<_1qH+2 z&h#mL-0hZ_+o)Bu>grpMU8(-ymk%L9VAM@S8wqz32>hI^GQajx)D@5j(hj1FzV?OCAnnCUet5;5ORjdEa_M-`HMB(9soY1pt}Kl)>*R@vV877(h6V$u2^hzg2nT*& z58PZvF%}H%KW@--@uCD^xyiG&U}1CY&Gn-I5#cv0_5?@_&9eVjRcAKx zA11{k(hmRHxx*DXIUc&CBM170147;fJYR~hWMzj|O=`Fgui-12n3dJeKcpM!^%Ox# zeJw45X8xHLB6>EKet!$6`r;P{_;k)I$`~I9htXhd)24ePgIe~I#a#CpypkGEy;+C;u?9sDlq?b5Lti4of#}yzU^30}Q&s{}l0Sbn_+_CgR{O!bIfI##e zgMV(%azyW`lef@EVKuLC(}639Mzo#gkNfv$u{v$V1u$R;h&m4eXLXi6*~xz^F$!@v zLv=MAVXNYNfdsA2M z@+0#O$6?qpmNOiWWU|hH;PwERfCMsuyvsnW%7QWtxDYl;kyEn<92=a-351Vh$37o! z#Wjc*szDkO96{m8L+Zuw=d|sNiUel}*8|cXKq1%1mX(|i{_G&XAGJK?>*Ir3RPgk- z2Fe2jeN-^I8qjsw51igYpjwer7LJ;s z_d-oWLsq2f6!O%9ie{da(DgZ!uz8F`(U>rB6eZpFYA*$QfppbrXxu^qdOd)Yy9&C83s4Rj%08u#+HBW+XT{9i+_B!>WMF0M+gHKO73@!D zwT^$JK>w1CZ{E`YZB12$MQAs_((0hwj5Nq!BLP#{Sxcy>>=#-RCl;>(u7I_5sFPwS_EpDf$58emv>?cSIU_q?;U* z)@Qecv+1}ykW8O*@&>??NdO$3Kit|5X$H@j%+Qb@L6qKD8KStZRkceJlF-aooD`h!=jN>z}(^Fwrf9fBEfzbrGp>VcK8%IrkTzaB=UK8!j%?n{0K{_%)%jl{-9BMVSt>BF-ib|ZTC5%*h6qfq$QZ`wpI~%6j5^v&gjKvJ%1FZbwdK*c3+) jw+%o4f5HECqjMFS4!8dcHIbzg literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-different-chains-2-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..29e076e9022cacb35c89efd3bc7639ca4eb5ea0f GIT binary patch literal 23313 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 - 2 * (verticalLineLength + DOUBLE_CORNER_LENGTH) && + 2 * (VERTICAL_LINE_LENGTH + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); @@ -427,15 +418,11 @@ export class PolymerBondRenderer extends BaseRenderer { ); } - private isSecondMonomerLeft( - startPosition: Vec2, - endPosition: Vec2, - verticalLineLength: number, - ): boolean { + private isSecondMonomerLeft(startPosition: Vec2, endPosition: Vec2): boolean { return ( startPosition.y - endPosition.y < 0 && startPosition.y - endPosition.y > - -2 * (verticalLineLength + DOUBLE_CORNER_LENGTH) && + -2 * (VERTICAL_LINE_LENGTH + DOUBLE_CORNER_LENGTH) && endPosition.x - startPosition.x <= DOUBLE_CORNER_LENGTH + LINE_FROM_MONOMER_LENGTH + this.getMonomerWidth() ); diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 1622272a26..73662f6043 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -46,7 +46,7 @@ import { const HORIZONTAL_DISTANCE_FROM_MONOMER = 50; const VERTICAL_DISTANCE_FROM_MONOMER = 60; -const RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER = 160; +const RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER = 60; const DISTANCE_FROM_RIGHT = 70; const DISTANCE_BETWEEN_MONOMERS = 30; const MONOMER_START_X_POSITION = 70; @@ -851,12 +851,12 @@ export class DrawingEntitiesManager { public getNucleotideSize(nucleotide: Nucleotide) { const width = - (nucleotide.sugar.renderer?.width || 0) + - (nucleotide.phosphate?.renderer?.width || 0) + + (nucleotide.sugar.renderer?.monomerSize.width || 0) + + (nucleotide.phosphate?.renderer?.monomerSize.width || 0) + 45; const height = - (nucleotide.sugar.renderer?.height || 0) + - (nucleotide.rnaBase?.renderer?.height || 0) + + (nucleotide.sugar.renderer?.monomerSize.height || 0) + + (nucleotide.rnaBase?.renderer?.monomerSize.height || 0) + 45; return { width, height }; } @@ -962,13 +962,19 @@ export class DrawingEntitiesManager { const newPositionOfModel = Coordinates.canvasToModel(lastPosition); const phosphatePositionOfModel = Coordinates.canvasToModel( new Vec2( - lastPosition.x + (nucleotide.sugar.renderer?.width ?? 0) + 45, + lastPosition.x + + (nucleotide.sugar.renderer?.monomerSize?.width ?? 0) / 2 + + (nucleotide.phosphate.renderer?.monomerSize?.width ?? 0) / 2 + + 45, lastPosition.y, ), ); const rnaBasePosition = new Vec2( lastPosition.x, - lastPosition.y + (nucleotide.sugar.renderer?.height ?? 0) + 45, + lastPosition.y + + (nucleotide.sugar.renderer?.monomerSize?.height ?? 0) / 2 + + (nucleotide.rnaBase.renderer?.monomerSize?.height ?? 0) / 2 + + 45, ); this.addRnaOperations( @@ -985,8 +991,7 @@ export class DrawingEntitiesManager { ); rearrangedMonomersSet.add(nucleotide.sugar.id); rearrangedMonomersSet.add(nucleotide.phosphate?.id); - // need to track the chain from rna base monomer - // TODO: would rna base chain contains other nucleotides? how to calculate the maxVerticalDistance? + // need to track the chain from rna base monomer, when rna base connected with other nucleotides or peptides const rearrangeBaseResult = this.reArrangeChainInRecursive( nucleotide.rnaBase, rnaBasePosition, From debbbe93c6c2f956987e271ef2ca87949654fa97 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Wed, 24 Jan 2024 17:29:16 +0800 Subject: [PATCH 07/18] #3869 add rearrange logic for nucleoside --- ...ge-for-peptides-chain-1-chromium-linux.png | Bin 0 -> 20237 bytes .../domain/entities/DrawingEntitiesManager.ts | 57 +++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-peptides-chain-1-chromium-linux.png diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-peptides-chain-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Check-snake-mode-arrange-for-peptides-chain-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..5e00bcc30575a9b28bbc3abe6619950ceb5019c8 GIT binary patch literal 20237 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 literal 0 HcmV?d00001 diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 73662f6043..ff523851ae 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -46,7 +46,6 @@ import { const HORIZONTAL_DISTANCE_FROM_MONOMER = 50; const VERTICAL_DISTANCE_FROM_MONOMER = 60; -const RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER = 60; const DISTANCE_FROM_RIGHT = 70; const DISTANCE_BETWEEN_MONOMERS = 30; const MONOMER_START_X_POSITION = 70; @@ -888,6 +887,16 @@ export class DrawingEntitiesManager { command.addOperation(operation); rearrangedMonomersSet.add(monomer.id); + // for nucleoSide, when base is connected to sugar (R3-R1), it should be aligned. + const rearrangeNucleoSideResult = this.reArrangeNucleoside( + monomer, + rearrangedMonomersSet, + lastPosition, + canvasWidth, + maxVerticalDistance, + command, + ); + command.merge(rearrangeNucleoSideResult.command); for (const attachmentPointName in monomer.attachmentPointsToBonds) { const polymerBond = monomer.attachmentPointsToBonds[attachmentPointName]; if (!polymerBond) { @@ -942,6 +951,50 @@ export class DrawingEntitiesManager { return { command, lastPosition, maxVerticalDistance }; } + private reArrangeNucleoside( + monomer: BaseMonomer, + rearrangedMonomersSet: Set, + lastPosition: Vec2, + canvasWidth: number, + maxVerticalDistance: number, + command: Command, + ) { + const r3PolymerBond = monomer.attachmentPointsToBonds.R3; + if (monomer instanceof Sugar && r3PolymerBond) { + const nextMonomer = + r3PolymerBond.secondMonomer === monomer + ? r3PolymerBond.firstMonomer + : r3PolymerBond.secondMonomer; + if ( + r3PolymerBond && + nextMonomer && + !rearrangedMonomersSet.has(nextMonomer.id) && + nextMonomer instanceof RNABase && + nextMonomer.getAttachmentPointByBond(r3PolymerBond) === 'R1' + ) { + const rnaBasePosition = new Vec2({ + x: lastPosition.x, + y: + lastPosition.y + + (monomer.renderer?.monomerSize?.height ?? 0) / 2 + + (nextMonomer.renderer?.monomerSize?.height ?? 0) / 2 + + 45, + }); + const rearrangeResult = this.reArrangeChainInRecursive( + nextMonomer, + rnaBasePosition, + canvasWidth, + rearrangedMonomersSet, + maxVerticalDistance, + ); + lastPosition = rearrangeResult.lastPosition; + maxVerticalDistance = rearrangeResult.maxVerticalDistance; + command.merge(rearrangeResult.command); + } + } + return { lastPosition, maxVerticalDistance, command }; + } + private reArrangeRnaChain( nucleotide: Nucleotide, lastPosition: Vec2, @@ -953,7 +1006,7 @@ export class DrawingEntitiesManager { const nucleotideSize = this.getNucleotideSize(nucleotide); const height = nucleotideSize.height; const width = nucleotideSize.width; - const heightWithBond = height + RNA_CHAIN_VERTICAL_DISTANCE_FROM_MONOMER; + const heightWithBond = height + VERTICAL_DISTANCE_FROM_MONOMER; maxVerticalDistance = Math.max(maxVerticalDistance, heightWithBond); nucleotide.sugar.isMonomerInRnaChainRow = true; nucleotide.phosphate.isMonomerInRnaChainRow = true; From fc7d6c7a1b62c99c32aadc50ae9881b22c35d75f Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Thu, 25 Jan 2024 15:19:29 +0800 Subject: [PATCH 08/18] #3869 small fix for code and test --- .../Polymer-Bond-Tool/snake-bond-tool.spec.ts | 113 +++++++++++++----- ...chain-with-nucleoside-1-chromium-linux.png | Bin 0 -> 14032 bytes ...chain-with-nucleoside-2-chromium-linux.png | Bin 0 -> 17059 bytes ...chain-with-nucleoside-3-chromium-linux.png | Bin 0 -> 9725 bytes .../domain/entities/DrawingEntitiesManager.ts | 3 +- 5 files changed, 83 insertions(+), 33 deletions(-) create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-2-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-3-chromium-linux.png diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts index e0c5a70147..69cd266fd3 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts @@ -302,7 +302,54 @@ test.describe('Snake Bond Tool', () => { await takeEditorScreenshot(page); }); - test('Create snake bond for different chains', async ({ page }) => { + test('Check snake mode arrange for RNA chain', async ({ page }) => { + await page.getByText('RNA').click(); + + await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); + await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); + await addRnaPresetOnCanvas(page, 'T_T_R_P', 800, 200); + await addRnaPresetOnCanvas(page, 'T_T_R_P', 100, 100); + + await selectSingleBondTool(page); + + const phosphate1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(0); + const phosphate2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(1); + const phosphate3 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(2); + const phosphate4 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(3); + const sugar1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(1); + const sugar2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(2); + const sugar3 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(3); + const sugar4 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(4); + + await bondTwoMonomers(page, phosphate1, sugar1); + await bondTwoMonomers(page, phosphate2, sugar2); + await bondTwoMonomers(page, phosphate3, sugar3); + await bondTwoMonomers(page, phosphate4, sugar4); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); + }); + + test('Create snake bond for mix chains with nucleotides and peptides', async ({ + page, + }) => { const peptide1 = await addMonomerToCanvas( page, MONOMER_NAME_TZA, @@ -409,46 +456,50 @@ test.describe('Snake Bond Tool', () => { await takeEditorScreenshot(page); }); - test('Check snake mode arrange for RNA chain', async ({ page }) => { + test('Create snake bond for chain with nucleoside', async ({ page }) => { await page.getByText('RNA').click(); + await selectSnakeBondTool(page); - await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); - await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); - await addRnaPresetOnCanvas(page, 'T_T_R_P', 800, 200); - await addRnaPresetOnCanvas(page, 'T_T_R_P', 100, 100); + await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 700, 300); + + await page.getByTestId('summary-Sugars').click(); + const sugarOfNucleoside = await addMonomerToCanvas( + page, + 'R___Ribose', + 'R', + 500, + 500, + 2, + ); + await page.getByTestId('summary-Bases').click(); + const baseOfNucleoside = await addMonomerToCanvas( + page, + 'A___Adenine', + 'A', + 600, + 600, + 1, + ); await selectSingleBondTool(page); + await bondTwoMonomers(page, sugarOfNucleoside, baseOfNucleoside); - const phosphate1 = await page + const phosphate = await page .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) .nth(0); - const phosphate2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(1); - const phosphate3 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(2); - const phosphate4 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(3); - const sugar1 = await page + + const sugar = await page .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) .nth(1); - const sugar2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(2); - const sugar3 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(3); - const sugar4 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(4); - await bondTwoMonomers(page, phosphate1, sugar1); - await bondTwoMonomers(page, phosphate2, sugar2); - await bondTwoMonomers(page, phosphate3, sugar3); - await bondTwoMonomers(page, phosphate4, sugar4); + await bondTwoMonomers(page, phosphate, sugarOfNucleoside); + await bondTwoMonomers(page, sugarOfNucleoside, sugar); + + await takeEditorScreenshot(page); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); await selectSnakeBondTool(page); await takeEditorScreenshot(page); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..7af39b6f5efc707cf2566fc2f1aa96182751a3b7 GIT binary patch literal 14032 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 P2ANziKVNwE#_fLr$pK4L literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-2-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..22043ab7246ee589e04b63a35e0b37a0b59a535a GIT binary patch literal 17059 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 literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-3-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-nucleoside-3-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..dac8ed625890fddba6c62527f27734465489bf39 GIT binary patch literal 9725 zcmeHNdpy(a-~Y-T73yAM4xy+}A}PnB?uJTnmmES?D2m3MCNpxoZ-&sB98y%uu{q9R zquXJX!;)ic%!WB_$YEo)J>Thm{r-5Ke}4Zwuh;LnpZlL}uj_kVpX+nIKkv`!`Y!%g zTWgsuN?QN`kU4W2b`b!?@c^(PeUk(@vSa_!SMWws6&#})YC)#&n)3V~z_;FDvD|ORcNY;b5R#qBT zEjccghx287dkEii`Ypx+iXR3RiQkQWyH8UyF~eLi-W$5ccF3Kl6(5czoGNndNfgd4 zPlgRB%G7SOPi4C`J&*HXkElRWj_v3?zADrsXqtG?fESS^`vzm>UP zvCkAxz~^j0h3}*1I;AxAz?I&iwMj(|mUWYI2J=sy$gsRCoLjdJqj%K|&c+Wla#Xrr zpo~T0(w91i0$iFtPW*brS?=wWIYOP*4zMvbh0cX))q97)6_(NdO=N4 zCpFZ&jru)lf<>u(Ar6PZdZw*rD5^mgT&v(Js$vgi=C{bTi|fJy13+OT2gbLuHF)`9 z)BZ`MQ?;!Tmu3SDi>F&iLuD3E@AVKK?w$zE<`^yGYo;js;Dcq%h(L71RvJ|KJ$GwNIpVmWuN{*_9d0*~8LET4GrDmB)jK zWaIZyZ%K$Pyu6(q4kK>Uzzaw5&6LS%MB&=3(C8_@imbZEWEo*J)zyc%WB$!jCDrq9 z&4=3jnw*GPocT&JwL2ceTaYQ2WKrdUsxW3A;rT-$=j_@`JZFo;`}Dn*?MyNY{;cj5 zJHe9Jjz`UWQw}1yyH&1?h7CT;px^dJB-j|*!eC9V&%l>7yQr3d z(DN7+H;E$-#SD6|t)rAXANR$!x3^GI1cu?;5C!PHr#yv^8>{!H`lm+NHz8qT_p}viT4e$5 z{5rbEHAjOF8K#_;ilwv#&(BqmvdvV=HP zH{qV=S9F;5V(;<2`PUCjyKngtP#gk$aRVtejA2(JUkoPsRt~Az3>0yb@@~hYEcowY zjCUk;CJyzM&Pp#v23lY8Hm_x02a?9YQ=T`x-*Dx)p;FYU6j`w;?#)Zk=qW=)>nZmZ zx8SN_P40@d-VezB;Uejx8y+z zh68JB2eteIc{N) zi*E1~iBbGXm-M<8?M=0D4kNgCkfn@oXqRjT&$wp~xPWlnBrdlw8yetO>MmOv=?>_) zZ%Ad_=lBb2Yf)Be8!(Ax-0tWH5GKX(=-VMt0pk_uvm@8tU|l*}B8T z#iH3JzL{FWl5d~%Od8>t_yw7nT&9=Ei%qwjs%xACu_sy6RIO^|aAS{Ggv6j}S_-Pi z!Kpc$D9nwq__85I*n0cGkS@%UrUC3vdgSH*Z{Ccit3(F#8@=P4Mdjns(b zSK004A|+U6RTcCrY6=~=nQR8b?Pz!RP?}9dQGu0}WTZ5pAP=HzU9Zb(@N1fO-+`Qp z#hS&=O}O98U!IHP9a{~#dCGIb?A8yP^!ZlAh3bH&HZ}(X;iHM+PtG;3hC+@wlss9h zvLk h=DxG=n3%nTk>u4FLO0uN0!nb0XZ{}(M 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 Date: Mon, 29 Jan 2024 17:50:40 +0800 Subject: [PATCH 09/18] #3869 refactor side chain logic --- .../domain/entities/DrawingEntitiesManager.ts | 459 ++++++++++-------- 1 file changed, 244 insertions(+), 215 deletions(-) diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 6ee977fcec..1252bfdc94 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -60,10 +60,11 @@ type RnaPresetAdditionParams = { phosphatePosition: Vec2 | undefined; }; -type Nucleotide = { +type NucleotideOrNucleoside = { sugar: Sugar; + phosphate?: Phosphate; rnaBase: RNABase; - phosphate: Phosphate; + baseMonomer: Sugar | Phosphate; }; export class DrawingEntitiesManager { @@ -848,14 +849,14 @@ export class DrawingEntitiesManager { return monomer; } - public getNucleotideSize(nucleotide: Nucleotide) { + public getNucleotideSize(nucleotide: NucleotideOrNucleoside) { const width = (nucleotide.sugar.renderer?.monomerSize.width || 0) + (nucleotide.phosphate?.renderer?.monomerSize.width || 0) + 45; const height = (nucleotide.sugar.renderer?.monomerSize.height || 0) + - (nucleotide.rnaBase?.renderer?.monomerSize.height || 0) + + (nucleotide.rnaBase.renderer?.monomerSize.height || 0) + 45; return { width, height }; } @@ -864,7 +865,8 @@ export class DrawingEntitiesManager { monomer: BaseMonomer, lastPosition: Vec2, canvasWidth: number, - rearrangedMonomersSet: Set = new Set(), + rearrangedMonomersSet: Set, + monomersWithSideChain: Array, maxVerticalDistance: number, ) { const command = new Command(); @@ -885,142 +887,36 @@ export class DrawingEntitiesManager { this.rearrangeChainModelChange.bind(this, monomer, oldMonomerPosition), ); command.addOperation(operation); - rearrangedMonomersSet.add(monomer.id); - // for nucleoSide, when base is connected to sugar (R3-R1), it should be aligned. - const rearrangeNucleoSideResult = this.reArrangeNucleoside( + + return this.reArrangeNextMonomer( monomer, - rearrangedMonomersSet, + monomerWidth, lastPosition, canvasWidth, + rearrangedMonomersSet, + monomersWithSideChain, maxVerticalDistance, + command, ); - command.merge(rearrangeNucleoSideResult.command); - for (const attachmentPointName in monomer.attachmentPointsToBonds) { - const polymerBond = monomer.attachmentPointsToBonds[attachmentPointName]; - if (!polymerBond) { - continue; - } - const nextMonomer = - polymerBond.secondMonomer === monomer - ? polymerBond.firstMonomer - : polymerBond.secondMonomer; - if (rearrangedMonomersSet.has(nextMonomer.id)) { - continue; - } - const positionAndDistance = this.getNextPositionAndDistance( - lastPosition, - monomerWidth, - maxVerticalDistance, - canvasWidth, - ); - lastPosition = positionAndDistance.lastPosition; - maxVerticalDistance = positionAndDistance.maxVerticalDistance; - if ( - (attachmentPointName === 'R2' && - nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1') || - (attachmentPointName === 'R1' && - nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2') - ) { - const rearrangeResult = this.reArrangeChainInRecursive( - nextMonomer, - lastPosition, - canvasWidth, - rearrangedMonomersSet, - maxVerticalDistance, - ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; - command.merge(rearrangeResult.command); - } else { - const diff = Vec2.diff(oldMonomerPosition, monomer.position); - const pos = Vec2.diff(nextMonomer.position, diff); - const rearrangeResult = this.reArrangeChainInRecursive( - nextMonomer, - Coordinates.modelToCanvas(pos), - canvasWidth, - rearrangedMonomersSet, - maxVerticalDistance, - ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; - command.merge(rearrangeResult.command); - } - } - return { command, lastPosition, maxVerticalDistance }; - } - - private reArrangeNucleoside( - monomer: BaseMonomer, - rearrangedMonomersSet: Set, - lastPosition: Vec2, - canvasWidth: number, - maxVerticalDistance: number, - ) { - const command = new Command(); - const r3PolymerBond = monomer.attachmentPointsToBonds.R3; - if (monomer instanceof Sugar && r3PolymerBond) { - const nextMonomer = - r3PolymerBond.secondMonomer === monomer - ? r3PolymerBond.firstMonomer - : r3PolymerBond.secondMonomer; - if ( - r3PolymerBond && - nextMonomer && - !rearrangedMonomersSet.has(nextMonomer.id) && - nextMonomer instanceof RNABase && - nextMonomer.getAttachmentPointByBond(r3PolymerBond) === 'R1' - ) { - const rnaBasePosition = new Vec2({ - x: lastPosition.x, - y: - lastPosition.y + - (monomer.renderer?.monomerSize?.height ?? 0) / 2 + - (nextMonomer.renderer?.monomerSize?.height ?? 0) / 2 + - 45, - }); - const rearrangeResult = this.reArrangeChainInRecursive( - nextMonomer, - rnaBasePosition, - canvasWidth, - rearrangedMonomersSet, - maxVerticalDistance, - ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; - command.merge(rearrangeResult.command); - } - } - return { lastPosition, maxVerticalDistance, command }; } private reArrangeRnaChain( - nucleotide: Nucleotide, + nucleotide: NucleotideOrNucleoside, lastPosition: Vec2, canvasWidth: number, - rearrangedMonomersSet: Set = new Set(), + rearrangedMonomersSet: Set, + monomersWithSideChain: Array, maxVerticalDistance: number, ) { const command = new Command(); const nucleotideSize = this.getNucleotideSize(nucleotide); - const height = nucleotideSize.height; - const width = nucleotideSize.width; + const { height, width } = nucleotideSize; const heightWithBond = height + VERTICAL_DISTANCE_FROM_MONOMER; maxVerticalDistance = Math.max(maxVerticalDistance, heightWithBond); nucleotide.sugar.isMonomerInRnaChainRow = true; - nucleotide.phosphate.isMonomerInRnaChainRow = true; - nucleotide.phosphate.isMonomerInRnaChainRow = true; + nucleotide.rnaBase.isMonomerInRnaChainRow = true; const oldSugarPosition = nucleotide.sugar.position; - const newPositionOfModel = Coordinates.canvasToModel(lastPosition); - const phosphatePositionOfModel = Coordinates.canvasToModel( - new Vec2( - lastPosition.x + - (nucleotide.sugar.renderer?.monomerSize?.width ?? 0) / 2 + - (nucleotide.phosphate.renderer?.monomerSize?.width ?? 0) / 2 + - 45, - lastPosition.y, - ), - ); const rnaBasePosition = new Vec2( lastPosition.x, lastPosition.y + @@ -1028,70 +924,134 @@ export class DrawingEntitiesManager { (nucleotide.rnaBase.renderer?.monomerSize?.height ?? 0) / 2 + 45, ); - this.addRnaOperations( command, oldSugarPosition, - newPositionOfModel, + lastPosition, nucleotide.sugar, ); this.addRnaOperations( command, - nucleotide.phosphate?.position, - phosphatePositionOfModel, - nucleotide.phosphate, + nucleotide.rnaBase?.position, + rnaBasePosition, + nucleotide.rnaBase, ); rearrangedMonomersSet.add(nucleotide.sugar.id); - rearrangedMonomersSet.add(nucleotide.phosphate?.id); - // need to track the chain from rna base monomer, when rna base connected with other nucleotides or peptides - const rearrangeBaseResult = this.reArrangeChainInRecursive( + rearrangedMonomersSet.add(nucleotide.rnaBase?.id); + + if (nucleotide.phosphate) { + nucleotide.phosphate.isMonomerInRnaChainRow = true; + const phosphatePosition = new Vec2( + lastPosition.x + + (nucleotide.sugar.renderer?.monomerSize?.width ?? 0) / 2 + + (nucleotide.phosphate?.renderer?.monomerSize?.width ?? 0) / 2 + + 45, + lastPosition.y, + ); + this.addRnaOperations( + command, + nucleotide.phosphate?.position, + phosphatePosition, + nucleotide.phosphate, + ); + rearrangedMonomersSet.add(nucleotide.phosphate?.id); + } + this.getRnaBaseSideChainMonomers( nucleotide.rnaBase, - rnaBasePosition, - canvasWidth, rearrangedMonomersSet, - maxVerticalDistance, + monomersWithSideChain, ); - command.merge(rearrangeBaseResult.command); - const polymerBond = nucleotide.phosphate?.attachmentPointsToBonds.R2; - if (!polymerBond) { - return { - command, - lastPosition, - maxVerticalDistance, - }; - } const nextMonomer = - polymerBond.secondMonomer === nucleotide.phosphate - ? polymerBond.firstMonomer - : polymerBond.secondMonomer; - if (!nextMonomer || rearrangedMonomersSet.has(nextMonomer.id)) { - return { - command, - lastPosition, - maxVerticalDistance, - }; - } - const positionAndDistance = this.getNextPositionAndDistance( - lastPosition, - width, - maxVerticalDistance, - canvasWidth, - ); - lastPosition = positionAndDistance.lastPosition; - maxVerticalDistance = positionAndDistance.maxVerticalDistance; - const rearrangeResult = this.reArrangeChainInRecursive( + nucleotide.baseMonomer === nucleotide.sugar && nucleotide.phosphate + ? nucleotide.phosphate + : nucleotide.sugar; + return this.reArrangeNextMonomer( nextMonomer, + width, lastPosition, canvasWidth, rearrangedMonomersSet, + monomersWithSideChain, maxVerticalDistance, + command, ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; - command.merge(rearrangeResult.command); + } + + private reArrangeNextMonomer( + monomer: BaseMonomer, + width: number, + lastPosition: Vec2, + canvasWidth: number, + rearrangedMonomersSet: Set, + monomersWithSideChain: Array, + maxVerticalDistance: number, + command: Command, + ) { + for (const attachmentPointName in monomer.attachmentPointsToBonds) { + const polymerBond = monomer.attachmentPointsToBonds[attachmentPointName]; + const nextMonomer = + polymerBond?.secondMonomer === monomer + ? polymerBond?.firstMonomer + : polymerBond?.secondMonomer; + if (!polymerBond || rearrangedMonomersSet.has(nextMonomer.id)) { + continue; + } + if ( + !( + attachmentPointName === 'R2' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1' + ) && + !( + attachmentPointName === 'R1' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2' + ) + ) { + monomersWithSideChain.push(nextMonomer); + } else { + ({ lastPosition, maxVerticalDistance } = + this.getNextPositionAndDistance( + lastPosition, + width, + maxVerticalDistance, + canvasWidth, + )); + const rearrangeResult = this.reArrangeChainInRecursive( + nextMonomer, + lastPosition, + canvasWidth, + rearrangedMonomersSet, + monomersWithSideChain, + maxVerticalDistance, + ); + ({ lastPosition, maxVerticalDistance } = rearrangeResult); + command.merge(rearrangeResult.command); + } + } return { command, lastPosition, maxVerticalDistance }; } + private getRnaBaseSideChainMonomers( + rnaBase: RNABase, + rearrangedMonomersSet: Set, + monomersWithSideChain: Array, + ) { + for (const attachmentPointName in rnaBase.attachmentPointsToBonds) { + const polymerBond = rnaBase.attachmentPointsToBonds[attachmentPointName]; + const nextMonomer = + polymerBond?.secondMonomer === rnaBase + ? polymerBond?.firstMonomer + : polymerBond?.secondMonomer; + if ( + !polymerBond || + !nextMonomer || + rearrangedMonomersSet.has(nextMonomer.id) + ) { + continue; + } + monomersWithSideChain.push(nextMonomer); + } + } + private addRnaOperations( command: Command, oldMonomerPosition: Vec2 | undefined, @@ -1102,7 +1062,11 @@ export class DrawingEntitiesManager { return; } const operation = new MonomerMoveOperation( - this.rearrangeChainModelChange.bind(this, monomer, newPosition), + this.rearrangeChainModelChange.bind( + this, + monomer, + Coordinates.canvasToModel(newPosition), + ), this.rearrangeChainModelChange.bind(this, monomer, oldMonomerPosition), ); command.addOperation(operation); @@ -1111,25 +1075,22 @@ export class DrawingEntitiesManager { public reArrangeChains(canvasWidth: number, isSnakeMode: boolean) { const command = new Command(); if (isSnakeMode) { - const firstMonomersInChains = this.getFirstMonomersInChains([ - Peptide, - Chem, - ]); - const firstRnaMonomersInChains = this.getFirstMonomersInChains([ - Sugar, - Phosphate, - ]); - const firstMonomers = firstMonomersInChains.concat( - firstRnaMonomersInChains, + const rearrangedMonomersSet: Set = new Set(); + const lastPosition = new Vec2({ + x: MONOMER_START_X_POSITION, + y: MONOMER_START_Y_POSITION, + }); + const firstMonomers = this.getFirstMonomersInChains( + [Peptide, Chem, Sugar, Phosphate], + [...this.monomers.values()], ); - firstMonomers.sort( - (monomer1, monomer2) => - monomer1.position.x + - monomer1.position.y - - (monomer2.position.x + monomer2.position.y), + const result = this.reArrangeMonomers( + canvasWidth, + firstMonomers, + rearrangedMonomersSet, + lastPosition, ); - const monomerCommand = this.reArrangeMonomers(canvasWidth, firstMonomers); - command.merge(monomerCommand); + command.merge(result.command); } command.merge(this.redrawBonds()); return command; @@ -1159,8 +1120,9 @@ export class DrawingEntitiesManager { MonomerTypes: Array< typeof Peptide | typeof Chem | typeof Phosphate | typeof Sugar >, + currentMonomers: BaseMonomer[], ) { - const monomersList = Array.from(this.monomers.values()).filter((monomer) => + const monomersList = currentMonomers.filter((monomer) => MonomerTypes.some((MonomerType) => monomer instanceof MonomerType), ); @@ -1180,7 +1142,7 @@ export class DrawingEntitiesManager { }); const filteredFirstMonomersInChains: BaseMonomer[] = []; - firstMonomersInChains.forEach((monomer, monomerIndex) => { + firstMonomersInChains.reverse().forEach((monomer, monomerIndex) => { const currentMonomerChain: BaseMonomer[] = this.findChainByMonomer(monomer); let isFirstMonomerInChain = true; @@ -1198,47 +1160,57 @@ export class DrawingEntitiesManager { filteredFirstMonomersInChains.push(monomer); } }); - return filteredFirstMonomersInChains; + return filteredFirstMonomersInChains.sort( + (monomer1, monomer2) => + monomer1.position.x + + monomer1.position.y - + (monomer2.position.x + monomer2.position.y), + ); } public reArrangeChainInRecursive( monomer: BaseMonomer, lastPosition: Vec2, canvasWidth: number, - rearrangedMonomersSet: Set = new Set(), + rearrangedMonomersSet: Set, + monomersWithSideChain: Array, maxVerticalDistance: number, ) { const command = new Command(); - let rearrangeResult; - - if (monomer instanceof Sugar) { - const nucleotide = getNucleotideFromFirstMonomer(monomer); - if (nucleotide) { - rearrangeResult = this.reArrangeRnaChain( - nucleotide, + if (monomer instanceof Sugar || monomer instanceof Phosphate) { + const nucleotideOrNucleoside = + getNucleotideOrNucleoSideFromFirstMonomer(monomer); + if (nucleotideOrNucleoside) { + const rearrangeRnaResult = this.reArrangeRnaChain( + nucleotideOrNucleoside, lastPosition, canvasWidth, rearrangedMonomersSet, + monomersWithSideChain, maxVerticalDistance, ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; - command.merge(rearrangeResult.command); - return { command, lastPosition, maxVerticalDistance }; + command.merge(rearrangeRnaResult.command); + return { + command, + lastPosition: rearrangeRnaResult.lastPosition, + maxVerticalDistance: rearrangeRnaResult.maxVerticalDistance, + }; } } - // if the first monomer is single sugar OR phosphate, snake-mode should still be applied to it - rearrangeResult = this.reArrangeChain( + const rearrangeResult = this.reArrangeChain( monomer, lastPosition, canvasWidth, rearrangedMonomersSet, + monomersWithSideChain, maxVerticalDistance, ); - lastPosition = rearrangeResult.lastPosition; - maxVerticalDistance = rearrangeResult.maxVerticalDistance; command.merge(rearrangeResult.command); - return { command, lastPosition, maxVerticalDistance }; + return { + command, + lastPosition: rearrangeResult.lastPosition, + maxVerticalDistance: rearrangeResult.maxVerticalDistance, + }; } public getNextPositionAndDistance( @@ -1271,31 +1243,57 @@ export class DrawingEntitiesManager { }; } - public reArrangeMonomers(canvasWidth: number, firstMonomers: BaseMonomer[]) { - let lastPosition = new Vec2({ - x: MONOMER_START_X_POSITION, - y: MONOMER_START_Y_POSITION, - }); + public reArrangeMonomers( + canvasWidth: number, + firstMonomers: BaseMonomer[], + rearrangedMonomersSet: Set, + lastPosition: Vec2, + ) { const command = new Command(); - // bonds connecting RNA monomers to the monomers of peptides or CHEMs should remain straight--no snake mode firstMonomers.forEach((monomer) => { + const monomersWithSideChain: Array = []; const rearrangeResult = this.reArrangeChainInRecursive( monomer, lastPosition, canvasWidth, - undefined, + rearrangedMonomersSet, + monomersWithSideChain, 0, ); command.merge(rearrangeResult.command); lastPosition = rearrangeResult.lastPosition; // need to calculate the vertical distance before the next row gets to display - // because the height of rna and peptide are different + // because the height of Rna and peptide are different lastPosition = getFirstPosition( rearrangeResult.maxVerticalDistance, lastPosition, ); + if (monomersWithSideChain.length > 0) { + monomersWithSideChain.forEach((monomerWithSideChain) => { + const currentMonomerChain: BaseMonomer[] = this.findChainByMonomer( + monomerWithSideChain, + undefined, + new Set([...rearrangedMonomersSet]), + ); + let firstMonomers = this.getFirstMonomersInChains( + [Peptide, Chem, Sugar, Phosphate], + currentMonomerChain, + ); + if (!firstMonomers.length) { + firstMonomers = [monomerWithSideChain]; + } + const rearrangeResult = this.reArrangeMonomers( + canvasWidth, + firstMonomers, + rearrangedMonomersSet, + lastPosition, + ); + command.merge(rearrangeResult.command); + lastPosition = rearrangeResult.lastPosition; + }); + } }); - return command; + return { command, lastPosition }; } public getPhosphateFromRnaBase(baseMonomer: RNABase) { @@ -1403,19 +1401,50 @@ function getFirstPosition(height: number, lastPosition: Vec2) { return new Vec2(MONOMER_START_X_POSITION, lastPosition.y + height); } -function getNucleotideFromFirstMonomer(monomer: BaseMonomer) { +function getNucleotideOrNucleoSideFromFirstMonomer( + monomer: BaseMonomer, +): NucleotideOrNucleoside | undefined { if (monomer instanceof Sugar) { const nextMonomer = getNextMonomerInChain(monomer); const rnaBaseMonomer = getRnaBaseMonomerFromSugar(monomer); + const isNucleoside = + !(nextMonomer instanceof Phosphate) && rnaBaseMonomer instanceof RNABase; const isNucleotide = - nextMonomer instanceof Phosphate && rnaBaseMonomer instanceof RNABase; + nextMonomer && + nextMonomer instanceof Phosphate && + rnaBaseMonomer instanceof RNABase; if (isNucleotide) { return { sugar: monomer, phosphate: nextMonomer, rnaBase: rnaBaseMonomer, - } as Nucleotide; + baseMonomer: monomer, + }; + } + if (isNucleoside) { + return { + sugar: monomer, + rnaBase: rnaBaseMonomer, + baseMonomer: monomer, + }; + } + } + if (monomer instanceof Phosphate) { + const r1PolymerBond = monomer.attachmentPointsToBonds.R1; + const nextMonomer = r1PolymerBond?.getAnotherMonomer(monomer); + const rnaBaseMonomer = getRnaBaseMonomerFromSugar(nextMonomer); + const isNucleotide = + nextMonomer && + nextMonomer instanceof Sugar && + rnaBaseMonomer instanceof RNABase; + if (isNucleotide) { + return { + sugar: nextMonomer, + phosphate: monomer, + rnaBase: rnaBaseMonomer, + baseMonomer: monomer, + }; } } - return null; + return undefined; } From 6a1a8257f2d456b4370ccb8fa907410d3e25f17f Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Mon, 29 Jan 2024 22:10:35 +0800 Subject: [PATCH 10/18] #3869 update screenshot --- .../Polymer-Bond-Tool/snake-bond-tool.spec.ts | 139 ++++++++++++++++++ ...hain-with-side-chains-1-chromium-linux.png | Bin 0 -> 29147 bytes ...hain-with-side-chains-2-chromium-linux.png | Bin 0 -> 30040 bytes ...leotides-and-peptides-1-chromium-linux.png | Bin 0 -> 25367 bytes ...leotides-and-peptides-2-chromium-linux.png | Bin 0 -> 23313 bytes ...leotides-and-peptides-3-chromium-linux.png | Bin 0 -> 22251 bytes .../domain/entities/DrawingEntitiesManager.ts | 2 +- 7 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-2-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-1-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-2-chromium-linux.png create mode 100644 ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-3-chromium-linux.png diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts index 69cd266fd3..3b57ac9830 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts @@ -504,4 +504,143 @@ test.describe('Snake Bond Tool', () => { await selectSnakeBondTool(page); await takeEditorScreenshot(page); }); + + test('Create snake bond for chain with side chains', async ({ page }) => { + await page.getByText('RNA').click(); + + await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); + await addRnaPresetOnCanvas(page, 'G_G_R_P', 500, 300); + await addRnaPresetOnCanvas(page, 'T_T_R_P', 700, 300); + await addRnaPresetOnCanvas(page, 'U_U_R_P', 900, 300); + + await page.getByTestId('summary-Sugars').click(); + const sugarOfNucleoside = await addMonomerToCanvas( + page, + 'R___Ribose', + 'R', + 350, + 350, + 4, + ); + await page.getByTestId('summary-Bases').click(); + const baseOfNucleoside = await addMonomerToCanvas( + page, + 'nC6n8A___6-Aminohexyl-8-aminoadenine', + 'nC6n8A', + 350, + 500, + 0, + ); + + await page.getByTestId('PEPTIDES-TAB').click(); + + const monomer1 = await addMonomerToCanvas( + page, + 'A___Alanine', + 'A', + 500, + 500, + 1, + ); + const monomer2 = await addMonomerToCanvas( + page, + 'Hcy___homocysteine', + 'Hcy', + 550, + 550, + 0, + ); + const monomer3 = await addMonomerToCanvas( + page, + 'A___Alanine', + 'A', + 600, + 600, + 2, + ); + const monomer4 = await addMonomerToCanvas( + page, + 'A___Alanine', + 'A', + 650, + 650, + 3, + ); + const monomer5 = await addMonomerToCanvas( + page, + 'A___Alanine', + 'A', + 700, + 700, + 4, + ); + const monomer6 = await addMonomerToCanvas( + page, + 'Bal___beta-Alanine', + 'Bal', + 600, + 500, + 0, + ); + const monomer7 = await addMonomerToCanvas( + page, + 'Bal___beta-Alanine', + 'Bal', + 650, + 500, + 1, + ); + const monomer8 = await addMonomerToCanvas( + page, + 'Bal___beta-Alanine', + 'Bal', + 750, + 500, + 2, + ); + + await selectSingleBondTool(page); + await bondTwoMonomers(page, sugarOfNucleoside, baseOfNucleoside); + await bondTwoMonomers(page, baseOfNucleoside, monomer1); + await page.locator('button[title=R2]').nth(0).click(); + await page.locator('button[title=R1]').nth(1).click(); + await page.locator('button[title=Connect]').click(); + + await bondTwoMonomers(page, monomer1, monomer2); + await bondTwoMonomers(page, monomer2, monomer3); + await bondTwoMonomers(page, monomer3, monomer4); + await bondTwoMonomers(page, monomer2, monomer5); + await page.locator('button[title=R1]').nth(1).click(); + await page.locator('button[title=Connect]').click(); + + const phosphate = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(0); + + const sugar = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(1); + const sugar1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(2); + const phosphate1 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(1); + const phosphate2 = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(2); + await bondTwoMonomers(page, phosphate, sugarOfNucleoside); + await bondTwoMonomers(page, sugarOfNucleoside, sugar); + await bondTwoMonomers(page, phosphate1, sugar1); + await bondTwoMonomers(page, phosphate2, monomer6); + await page.locator('button[title=R1]').nth(1).click(); + await page.locator('button[title=Connect]').click(); + await bondTwoMonomers(page, monomer6, monomer7); + await bondTwoMonomers(page, monomer7, monomer8); + + await takeEditorScreenshot(page); + + await selectSnakeBondTool(page); + await takeEditorScreenshot(page); + }); }); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-1-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..e53f893234b51fc2e26f97c1a9dca4949e8b92fd GIT binary patch literal 29147 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 literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-2-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..29e076e9022cacb35c89efd3bc7639ca4eb5ea0f GIT binary patch literal 23313 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 Date: Tue, 30 Jan 2024 18:12:58 +0800 Subject: [PATCH 11/18] #3869 enhancement --- .../Polymer-Bond-Tool/snake-bond-tool.spec.ts | 270 ++++++++++-------- .../tests/utils/canvas/helpers.ts | 10 + .../tests/utils/macromolecules/polymerBond.ts | 12 + .../src/application/editor/tools/RnaPreset.ts | 5 +- .../render/renderers/PolymerBondRenderer.ts | 23 +- .../src/domain/entities/BaseMonomer.ts | 4 + .../ketcher-core/src/domain/entities/Chem.ts | 8 + .../domain/entities/DrawingEntitiesManager.ts | 62 ++-- .../src/domain/entities/Peptide.ts | 8 + .../src/domain/entities/Phosphate.ts | 6 + .../ketcher-core/src/domain/entities/Sugar.ts | 6 + 11 files changed, 236 insertions(+), 178 deletions(-) diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts index 3b57ac9830..850dd799b1 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts @@ -275,29 +275,35 @@ test.describe('Snake Bond Tool', () => { await page.getByText('RNA').click(); await selectSnakeBondTool(page); - await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); - await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); + const { phosphate } = await addRnaPresetOnCanvas( + page, + 'A_A_R_P', + 300, + 300, + 0, + 0, + ); + const { sugar: sugar1, phosphate: phosphate1 } = await addRnaPresetOnCanvas( + page, + 'C_C_R_P', + 400, + 600, + 1, + 1, + ); + const { sugar: sugar2 } = await addRnaPresetOnCanvas( + page, + 'G_G_R_P', + 600, + 400, + 2, + 2, + ); await selectSingleBondTool(page); - const phosphate1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(0); - - const phosphate2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(1); - - const sugar1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(1); - const sugar2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(2); - - await bondTwoMonomers(page, phosphate1, sugar1); - await bondTwoMonomers(page, phosphate2, sugar2); + await bondTwoMonomers(page, phosphate, sugar1); + await bondTwoMonomers(page, phosphate1, sugar2); await takeEditorScreenshot(page); }); @@ -305,43 +311,53 @@ test.describe('Snake Bond Tool', () => { test('Check snake mode arrange for RNA chain', async ({ page }) => { await page.getByText('RNA').click(); - await addRnaPresetOnCanvas(page, 'A_A_R_P', 300, 300); - await addRnaPresetOnCanvas(page, 'C_C_R_P', 400, 600); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 600, 400); - await addRnaPresetOnCanvas(page, 'T_T_R_P', 800, 200); - await addRnaPresetOnCanvas(page, 'T_T_R_P', 100, 100); + const { phosphate } = await addRnaPresetOnCanvas( + page, + 'A_A_R_P', + 300, + 300, + 0, + 0, + ); + const { sugar: sugar1, phosphate: phosphate1 } = await addRnaPresetOnCanvas( + page, + 'C_C_R_P', + 400, + 600, + 1, + 1, + ); + const { sugar: sugar2, phosphate: phosphate2 } = await addRnaPresetOnCanvas( + page, + 'G_G_R_P', + 600, + 400, + 2, + 2, + ); + const { sugar: sugar3, phosphate: phosphate3 } = await addRnaPresetOnCanvas( + page, + 'T_T_R_P', + 800, + 200, + 3, + 3, + ); + const { sugar: sugar4 } = await addRnaPresetOnCanvas( + page, + 'T_T_R_P', + 100, + 100, + 4, + 4, + ); await selectSingleBondTool(page); - const phosphate1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(0); - const phosphate2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(1); - const phosphate3 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(2); - const phosphate4 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(3); - const sugar1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(1); - const sugar2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(2); - const sugar3 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(3); - const sugar4 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(4); - - await bondTwoMonomers(page, phosphate1, sugar1); - await bondTwoMonomers(page, phosphate2, sugar2); - await bondTwoMonomers(page, phosphate3, sugar3); - await bondTwoMonomers(page, phosphate4, sugar4); + await bondTwoMonomers(page, phosphate, sugar1); + await bondTwoMonomers(page, phosphate1, sugar2); + await bondTwoMonomers(page, phosphate2, sugar3); + await bondTwoMonomers(page, phosphate3, sugar4); await selectSnakeBondTool(page); await takeEditorScreenshot(page); @@ -411,35 +427,36 @@ test.describe('Snake Bond Tool', () => { await page.getByText('RNA').click(); await selectSnakeBondTool(page); - await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); - await addRnaPresetOnCanvas(page, 'C_C_R_P', 300, 500); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 400, 300); + const { phosphate } = await addRnaPresetOnCanvas( + page, + 'A_A_R_P', + 200, + 200, + 0, + 0, + ); + const { sugar: sugar1, phosphate: phosphate1 } = await addRnaPresetOnCanvas( + page, + 'C_C_R_P', + 300, + 500, + 1, + 1, + ); + const { sugar: sugar2, phosphate: phosphate2 } = await addRnaPresetOnCanvas( + page, + 'G_G_R_P', + 400, + 300, + 2, + 2, + ); await selectSingleBondTool(page); - const phosphate1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(0); - const phosphate2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(1); - const phosphate3 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(2); - - const sugar1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(1); - const sugar2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(2); - - await bondTwoMonomers(page, phosphate1, sugar1); - await bondTwoMonomers(page, phosphate2, sugar2); - await bondTwoMonomers(page, phosphate3, peptide1); - - await page.locator('button[title=R1]').nth(1).click(); - await page.locator('button[title=Connect]').click(); + await bondTwoMonomers(page, phosphate, sugar1); + await bondTwoMonomers(page, phosphate1, sugar2); + await bondTwoMonomers(page, phosphate2, peptide1, undefined, 'R1'); await bondTwoMonomers(page, peptide1, peptide2); await bondTwoMonomers(page, peptide2, peptide3); @@ -460,8 +477,22 @@ test.describe('Snake Bond Tool', () => { await page.getByText('RNA').click(); await selectSnakeBondTool(page); - await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 700, 300); + const { phosphate } = await addRnaPresetOnCanvas( + page, + 'A_A_R_P', + 200, + 200, + 0, + 0, + ); + const { sugar } = await addRnaPresetOnCanvas( + page, + 'G_G_R_P', + 700, + 300, + 1, + 1, + ); await page.getByTestId('summary-Sugars').click(); const sugarOfNucleoside = await addMonomerToCanvas( @@ -484,15 +515,6 @@ test.describe('Snake Bond Tool', () => { await selectSingleBondTool(page); await bondTwoMonomers(page, sugarOfNucleoside, baseOfNucleoside); - - const phosphate = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(0); - - const sugar = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(1); - await bondTwoMonomers(page, phosphate, sugarOfNucleoside); await bondTwoMonomers(page, sugarOfNucleoside, sugar); @@ -507,12 +529,31 @@ test.describe('Snake Bond Tool', () => { test('Create snake bond for chain with side chains', async ({ page }) => { await page.getByText('RNA').click(); - - await addRnaPresetOnCanvas(page, 'A_A_R_P', 200, 200); - await addRnaPresetOnCanvas(page, 'G_G_R_P', 500, 300); - await addRnaPresetOnCanvas(page, 'T_T_R_P', 700, 300); - await addRnaPresetOnCanvas(page, 'U_U_R_P', 900, 300); - + const { phosphate } = await addRnaPresetOnCanvas( + page, + 'A_A_R_P', + 200, + 200, + 0, + 0, + ); + const { sugar: sugar1, phosphate: phosphate1 } = await addRnaPresetOnCanvas( + page, + 'G_G_R_P', + 500, + 300, + 1, + 1, + ); + const { sugar: sugar2, phosphate: phosphate2 } = await addRnaPresetOnCanvas( + page, + 'T_T_R_P', + 700, + 300, + 2, + 2, + ); + await addRnaPresetOnCanvas(page, 'U_U_R_P', 900, 300, 3, 3); await page.getByTestId('summary-Sugars').click(); const sugarOfNucleoside = await addMonomerToCanvas( page, @@ -601,40 +642,17 @@ test.describe('Snake Bond Tool', () => { await selectSingleBondTool(page); await bondTwoMonomers(page, sugarOfNucleoside, baseOfNucleoside); - await bondTwoMonomers(page, baseOfNucleoside, monomer1); - await page.locator('button[title=R2]').nth(0).click(); - await page.locator('button[title=R1]').nth(1).click(); - await page.locator('button[title=Connect]').click(); + await bondTwoMonomers(page, baseOfNucleoside, monomer1, 'R2', 'R1'); await bondTwoMonomers(page, monomer1, monomer2); await bondTwoMonomers(page, monomer2, monomer3); await bondTwoMonomers(page, monomer3, monomer4); - await bondTwoMonomers(page, monomer2, monomer5); - await page.locator('button[title=R1]').nth(1).click(); - await page.locator('button[title=Connect]').click(); - - const phosphate = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(0); - - const sugar = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(1); - const sugar1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) - .nth(2); - const phosphate1 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(1); - const phosphate2 = await page - .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) - .nth(2); + await bondTwoMonomers(page, monomer2, monomer5, undefined, 'R1'); + await bondTwoMonomers(page, phosphate, sugarOfNucleoside); - await bondTwoMonomers(page, sugarOfNucleoside, sugar); - await bondTwoMonomers(page, phosphate1, sugar1); - await bondTwoMonomers(page, phosphate2, monomer6); - await page.locator('button[title=R1]').nth(1).click(); - await page.locator('button[title=Connect]').click(); + await bondTwoMonomers(page, sugarOfNucleoside, sugar1); + await bondTwoMonomers(page, phosphate1, sugar2); + await bondTwoMonomers(page, phosphate2, monomer6, undefined, 'R1'); await bondTwoMonomers(page, monomer6, monomer7); await bondTwoMonomers(page, monomer7, monomer8); diff --git a/ketcher-autotests/tests/utils/canvas/helpers.ts b/ketcher-autotests/tests/utils/canvas/helpers.ts index fc9151ae81..d5c6f84be9 100644 --- a/ketcher-autotests/tests/utils/canvas/helpers.ts +++ b/ketcher-autotests/tests/utils/canvas/helpers.ts @@ -330,10 +330,20 @@ export async function addRnaPresetOnCanvas( presetId: string, positionX: number, positionY: number, + sugarIndex: number, + phosphateIndex: number, ) { await page.getByTestId(presetId).click(); await page.mouse.click(positionX, positionY); await hideMonomerPreview(page); + const sugar = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='R']]`) + .nth(sugarIndex); + const phosphate = await page + .locator(`//\*[name() = 'g' and ./\*[name()='text' and .='P']]`) + .nth(phosphateIndex); + + return { sugar, phosphate }; } export async function addChemOnCanvas(page: Page, chemId: string) { diff --git a/ketcher-autotests/tests/utils/macromolecules/polymerBond.ts b/ketcher-autotests/tests/utils/macromolecules/polymerBond.ts index 0b7eb58506..35d23ac75f 100644 --- a/ketcher-autotests/tests/utils/macromolecules/polymerBond.ts +++ b/ketcher-autotests/tests/utils/macromolecules/polymerBond.ts @@ -5,10 +5,22 @@ export async function bondTwoMonomers( page: Page, firstMonomerElement: Locator, secondMonomerElement: Locator, + connectTitle1?: string, + connectTitle2?: string, ) { await firstMonomerElement.hover(); await page.mouse.down(); await secondMonomerElement.hover(); await page.mouse.up(); await hideMonomerPreview(page); + const dialog = await page.getByRole('dialog'); + if (await dialog.isVisible()) { + if (connectTitle1) { + await page.locator(`button[title='${connectTitle1}']`).nth(0).click(); + } + if (connectTitle2) { + await page.locator(`button[title='${connectTitle2}']`).nth(1).click(); + } + await page.locator('button[title=Connect]').click(); + } } diff --git a/packages/ketcher-core/src/application/editor/tools/RnaPreset.ts b/packages/ketcher-core/src/application/editor/tools/RnaPreset.ts index 4d85cb41a0..2cb6ea281c 100644 --- a/packages/ketcher-core/src/application/editor/tools/RnaPreset.ts +++ b/packages/ketcher-core/src/application/editor/tools/RnaPreset.ts @@ -25,6 +25,7 @@ import { RNABase } from 'domain/entities/RNABase'; import { Phosphate } from 'domain/entities/Phosphate'; import { Coordinates } from '../shared/coordinates'; +export const RNA_MONOMER_DISTANCE = 45; class RnaPresetTool implements Tool { rnaBase: MonomerItemType | undefined; sugar: MonomerItemType | undefined; @@ -78,7 +79,7 @@ class RnaPresetTool implements Tool { new Vec2( this.editor.lastCursorPositionOfCanvas.x + this.sugarPreviewRenderer?.width + - 45, + RNA_MONOMER_DISTANCE, this.editor.lastCursorPositionOfCanvas.y, ), ) @@ -90,7 +91,7 @@ class RnaPresetTool implements Tool { this.editor.lastCursorPositionOfCanvas.x, this.editor.lastCursorPositionOfCanvas.y + this.sugarPreviewRenderer.height + - 45, + RNA_MONOMER_DISTANCE, ), ) : undefined, diff --git a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts index 8d1d430dd0..1935450c4b 100644 --- a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts @@ -45,30 +45,15 @@ export class PolymerBondRenderer extends BaseRenderer { ); } - private isMonomersTypeDifferent() { - return ( - (this.polymerBond.secondMonomer && - [Peptide, Chem].some( - (type) => this.polymerBond.firstMonomer instanceof type, - ) && - [Sugar, Phosphate].some( - (type) => this.polymerBond.secondMonomer instanceof type, - )) || - ([Peptide, Chem].some( - (type) => this.polymerBond.secondMonomer instanceof type, - ) && - [Sugar, Phosphate].some( - (type) => this.polymerBond.firstMonomer instanceof type, - )) - ); - } - get isSnake() { if ( !this.isSnakeBondAvailableForMonomer(this.polymerBond.firstMonomer) || (this.polymerBond.secondMonomer && !this.isSnakeBondAvailableForMonomer(this.polymerBond.secondMonomer)) || - this.isMonomersTypeDifferent() + (this.polymerBond.secondMonomer && + this.polymerBond.firstMonomer.isMonomerTypeDifferentForSnakeMode( + this.polymerBond.secondMonomer, + )) ) { return false; } diff --git a/packages/ketcher-core/src/domain/entities/BaseMonomer.ts b/packages/ketcher-core/src/domain/entities/BaseMonomer.ts index f25bf95ff8..1191b70ff9 100644 --- a/packages/ketcher-core/src/domain/entities/BaseMonomer.ts +++ b/packages/ketcher-core/src/domain/entities/BaseMonomer.ts @@ -444,4 +444,8 @@ export abstract class BaseMonomer extends DrawingEntity { return this.firstFreeAttachmentPoint; } + + public isMonomerTypeDifferentForSnakeMode(_monomerToChain: BaseMonomer) { + return true; + } } diff --git a/packages/ketcher-core/src/domain/entities/Chem.ts b/packages/ketcher-core/src/domain/entities/Chem.ts index 9c7f9efe3a..b702e71d88 100644 --- a/packages/ketcher-core/src/domain/entities/Chem.ts +++ b/packages/ketcher-core/src/domain/entities/Chem.ts @@ -1,5 +1,7 @@ import { BaseMonomer } from 'domain/entities/BaseMonomer'; import { Peptide } from 'domain/entities/Peptide'; +import { Sugar } from './Sugar'; +import { Phosphate } from './Phosphate'; export class Chem extends BaseMonomer { public getValidSourcePoint(monomer?: BaseMonomer) { @@ -9,4 +11,10 @@ export class Chem extends BaseMonomer { public getValidTargetPoint(monomer: BaseMonomer) { return Peptide.prototype.getValidTargetPoint.call(this, monomer); } + + public isMonomerTypeDifferentForSnakeMode(monomerToChain: BaseMonomer) { + return ( + monomerToChain instanceof Sugar || monomerToChain instanceof Phosphate + ); + } } diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 891374e6cd..3df916153c 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -43,6 +43,7 @@ import { getNextMonomerInChain, getRnaBaseMonomerFromSugar, } from 'domain/helpers/monomers'; +import { RNA_MONOMER_DISTANCE } from 'application/editor/tools/RnaPreset'; const HORIZONTAL_DISTANCE_FROM_MONOMER = 50; const VERTICAL_DISTANCE_FROM_MONOMER = 60; @@ -853,11 +854,11 @@ export class DrawingEntitiesManager { const width = (nucleotide.sugar.renderer?.monomerSize.width || 0) + (nucleotide.phosphate?.renderer?.monomerSize.width || 0) + - (nucleotide.phosphate ? 45 : 0); + (nucleotide.phosphate ? RNA_MONOMER_DISTANCE : 0); const height = (nucleotide.sugar.renderer?.monomerSize.height || 0) + (nucleotide.rnaBase.renderer?.monomerSize.height || 0) + - 45; + RNA_MONOMER_DISTANCE; return { width, height }; } @@ -922,7 +923,7 @@ export class DrawingEntitiesManager { lastPosition.y + (nucleotide.sugar.renderer?.monomerSize?.height ?? 0) / 2 + (nucleotide.rnaBase.renderer?.monomerSize?.height ?? 0) / 2 + - 45, + RNA_MONOMER_DISTANCE, ); this.addRnaOperations( command, @@ -945,7 +946,7 @@ export class DrawingEntitiesManager { lastPosition.x + (nucleotide.sugar.renderer?.monomerSize?.width ?? 0) / 2 + (nucleotide.phosphate?.renderer?.monomerSize?.width ?? 0) / 2 + - 45, + RNA_MONOMER_DISTANCE, lastPosition.y, ); this.addRnaOperations( @@ -956,16 +957,11 @@ export class DrawingEntitiesManager { ); rearrangedMonomersSet.add(nucleotide.phosphate?.id); } - this.getRnaBaseSideChainMonomers( - nucleotide.rnaBase, - rearrangedMonomersSet, - monomersWithSideChain, - ); const nextMonomer = nucleotide.baseMonomer === nucleotide.sugar && nucleotide.phosphate ? nucleotide.phosphate : nucleotide.sugar; - return this.reArrangeNextMonomer( + const nextMonomerResult = this.reArrangeNextMonomer( nextMonomer, width, lastPosition, @@ -975,6 +971,15 @@ export class DrawingEntitiesManager { maxVerticalDistance, command, ); + command.merge(nextMonomerResult.command); + ({ lastPosition, maxVerticalDistance } = nextMonomerResult); + + this.getRnaBaseSideChainMonomers( + nucleotide.rnaBase, + rearrangedMonomersSet, + monomersWithSideChain, + ); + return { command, lastPosition, maxVerticalDistance }; } private reArrangeNextMonomer( @@ -989,25 +994,16 @@ export class DrawingEntitiesManager { ) { for (const attachmentPointName in monomer.attachmentPointsToBonds) { const polymerBond = monomer.attachmentPointsToBonds[attachmentPointName]; - const nextMonomer = - polymerBond?.secondMonomer === monomer - ? polymerBond?.firstMonomer - : polymerBond?.secondMonomer; + const nextMonomer = polymerBond?.getAnotherMonomer(monomer); if (!polymerBond || rearrangedMonomersSet.has(nextMonomer.id)) { continue; } if ( - !( - attachmentPointName === 'R2' && - nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1' - ) && - !( - attachmentPointName === 'R1' && - nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2' - ) + (attachmentPointName === 'R2' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1') || + (attachmentPointName === 'R1' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2') ) { - monomersWithSideChain.push(nextMonomer); - } else { ({ lastPosition, maxVerticalDistance } = this.getNextPositionAndDistance( lastPosition, @@ -1025,6 +1021,8 @@ export class DrawingEntitiesManager { ); ({ lastPosition, maxVerticalDistance } = rearrangeResult); command.merge(rearrangeResult.command); + } else { + monomersWithSideChain.push(nextMonomer); } } return { command, lastPosition, maxVerticalDistance }; @@ -1035,12 +1033,11 @@ export class DrawingEntitiesManager { rearrangedMonomersSet: Set, monomersWithSideChain: Array, ) { - for (const attachmentPointName in rnaBase.attachmentPointsToBonds) { + for (const attachmentPointName of Object.keys( + rnaBase.attachmentPointsToBonds, + ).reverse()) { const polymerBond = rnaBase.attachmentPointsToBonds[attachmentPointName]; - const nextMonomer = - polymerBond?.secondMonomer === rnaBase - ? polymerBond?.firstMonomer - : polymerBond?.secondMonomer; + const nextMonomer = polymerBond?.getAnotherMonomer(rnaBase); if ( !polymerBond || !nextMonomer || @@ -1269,7 +1266,7 @@ export class DrawingEntitiesManager { lastPosition, ); if (monomersWithSideChain.length > 0) { - monomersWithSideChain.forEach((monomerWithSideChain) => { + monomersWithSideChain.reverse().forEach((monomerWithSideChain) => { const currentMonomerChain: BaseMonomer[] = this.findChainByMonomer( monomerWithSideChain, undefined, @@ -1279,7 +1276,10 @@ export class DrawingEntitiesManager { [Peptide, Chem, Sugar, Phosphate], currentMonomerChain, ); - if (!firstMonomers.length) { + if ( + !firstMonomers.length && + !rearrangedMonomersSet.has(monomerWithSideChain.id) + ) { firstMonomers = [monomerWithSideChain]; } const rearrangeResult = this.reArrangeMonomers( diff --git a/packages/ketcher-core/src/domain/entities/Peptide.ts b/packages/ketcher-core/src/domain/entities/Peptide.ts index b62f34adf0..af589d5607 100644 --- a/packages/ketcher-core/src/domain/entities/Peptide.ts +++ b/packages/ketcher-core/src/domain/entities/Peptide.ts @@ -1,4 +1,6 @@ import { BaseMonomer } from './BaseMonomer'; +import { Phosphate } from './Phosphate'; +import { Sugar } from './Sugar'; export class Peptide extends BaseMonomer { public getValidSourcePoint(secondMonomer?: BaseMonomer) { @@ -76,4 +78,10 @@ export class Peptide extends BaseMonomer { return undefined; } + + public isMonomerTypeDifferentForSnakeMode(monomerToChain: BaseMonomer) { + return ( + monomerToChain instanceof Sugar || monomerToChain instanceof Phosphate + ); + } } diff --git a/packages/ketcher-core/src/domain/entities/Phosphate.ts b/packages/ketcher-core/src/domain/entities/Phosphate.ts index 2e9ca827f4..f7f922294c 100644 --- a/packages/ketcher-core/src/domain/entities/Phosphate.ts +++ b/packages/ketcher-core/src/domain/entities/Phosphate.ts @@ -2,6 +2,8 @@ import { BaseMonomer } from './BaseMonomer'; import { MonomerItemType } from 'domain/types'; import { Vec2 } from './vec2'; import { Sugar } from './Sugar'; +import { Peptide } from './Peptide'; +import { Chem } from './Chem'; export class Phosphate extends BaseMonomer { constructor(monomerItem: MonomerItemType, _position?: Vec2) { @@ -79,4 +81,8 @@ export class Phosphate extends BaseMonomer { return undefined; } + + public isMonomerTypeDifferentForSnakeMode(monomerToChain: BaseMonomer) { + return monomerToChain instanceof Peptide || monomerToChain instanceof Chem; + } } diff --git a/packages/ketcher-core/src/domain/entities/Sugar.ts b/packages/ketcher-core/src/domain/entities/Sugar.ts index c497b70c20..6922f1b039 100644 --- a/packages/ketcher-core/src/domain/entities/Sugar.ts +++ b/packages/ketcher-core/src/domain/entities/Sugar.ts @@ -1,6 +1,8 @@ import { BaseMonomer } from './BaseMonomer'; import { RNABase } from './RNABase'; import { Phosphate } from './Phosphate'; +import { Peptide } from './Peptide'; +import { Chem } from './Chem'; export class Sugar extends BaseMonomer { public getValidSourcePoint(secondMonomer: BaseMonomer) { @@ -90,4 +92,8 @@ export class Sugar extends BaseMonomer { return undefined; } + + public isMonomerTypeDifferentForSnakeMode(monomerToChain: BaseMonomer) { + return monomerToChain instanceof Peptide || monomerToChain instanceof Chem; + } } From 639f7835403e6f4a6dcb9047ef90fb0dd2a4378a Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Tue, 30 Jan 2024 18:23:05 +0800 Subject: [PATCH 12/18] # 3869 fix issue --- .../ketcher-core/src/domain/entities/DrawingEntitiesManager.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index 3df916153c..468fd9b190 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -971,7 +971,6 @@ export class DrawingEntitiesManager { maxVerticalDistance, command, ); - command.merge(nextMonomerResult.command); ({ lastPosition, maxVerticalDistance } = nextMonomerResult); this.getRnaBaseSideChainMonomers( From f53ce8084dfbd3047beceb41b3f0f5f96ec9f8b8 Mon Sep 17 00:00:00 2001 From: Starla Huang Date: Wed, 31 Jan 2024 15:08:46 +0800 Subject: [PATCH 13/18] #3869 fix snake mode issue for same attachment points and autotests --- .../Clear-Tool/clear-tool.spec.ts | 10 +- .../Erase-Tool/erase-tool.spec.ts | 10 +- .../Modal-window/modal-window.spec.ts | 22 +- .../attachment-point-hover.spec.ts | 6 +- .../attachment-point-rotation.spec.ts | 14 +- .../polymer-bond-tool.spec.ts | 14 +- .../Polymer-Bond-Tool/snake-bond-tool.spec.ts | 254 ++++-------------- ...hain-with-side-chains-1-chromium-linux.png | Bin 29147 -> 31822 bytes ...hain-with-side-chains-2-chromium-linux.png | Bin 30040 -> 30036 bytes .../Polymer-Bond-Tool/zoom-tool.spec.ts | 4 +- .../rectangle-selection-tool.spec.ts | 18 +- .../Undo-Redo/undo-redo.spec.ts | 8 +- .../tests/utils/canvas/helpers.ts | 39 ++- .../tests/utils/macromolecules/polymerBond.ts | 10 +- .../render/renderers/PolymerBondRenderer.ts | 17 +- 15 files changed, 167 insertions(+), 259 deletions(-) diff --git a/ketcher-autotests/tests/Macromolecule-editor/Clear-Tool/clear-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Clear-Tool/clear-tool.spec.ts index 80f87b8f76..988a9ef617 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Clear-Tool/clear-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Clear-Tool/clear-tool.spec.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, selectClearCanvasTool, selectSingleBondTool, takeEditorScreenshot, @@ -27,7 +27,7 @@ test.describe('Clear Canvas Tool', () => { const MONOMER_NAME = 'Tza___3-thiazolylalanine'; const MONOMER_ALIAS = 'Tza'; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -35,7 +35,7 @@ test.describe('Clear Canvas Tool', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -43,7 +43,7 @@ test.describe('Clear Canvas Tool', () => { 400, 1, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -51,7 +51,7 @@ test.describe('Clear Canvas Tool', () => { 500, 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, diff --git a/ketcher-autotests/tests/Macromolecule-editor/Erase-Tool/erase-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Erase-Tool/erase-tool.spec.ts index 75a392d0e1..42196b3cec 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Erase-Tool/erase-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Erase-Tool/erase-tool.spec.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, selectEraseTool, selectSingleBondTool, takeEditorScreenshot, @@ -29,7 +29,7 @@ test.describe('Erase Tool', () => { const MONOMER_NAME = 'Tza___3-thiazolylalanine'; const MONOMER_ALIAS = 'Tza'; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -37,7 +37,7 @@ test.describe('Erase Tool', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -45,7 +45,7 @@ test.describe('Erase Tool', () => { 400, 1, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -53,7 +53,7 @@ test.describe('Erase Tool', () => { 500, 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, diff --git a/ketcher-autotests/tests/Macromolecule-editor/Modal-window/modal-window.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Modal-window/modal-window.spec.ts index 48c6352313..bb472cd090 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Modal-window/modal-window.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Modal-window/modal-window.spec.ts @@ -1,6 +1,6 @@ import { Locator, test } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, selectSingleBondTool, takeEditorScreenshot, waitForPageInit, @@ -19,7 +19,7 @@ test.describe('Modal window', () => { const MONOMER_NAME = 'Test-6-Ch___Test-6-AP-Chem'; const MONOMER_ALIAS = 'Test-6-Ch'; - peptide1 = await addMonomerToCanvas( + peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -27,7 +27,7 @@ test.describe('Modal window', () => { 200, 0, ); - peptide2 = await addMonomerToCanvas( + peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -51,7 +51,15 @@ test.describe('Modal window', () => { */ // Create bonds between peptides - await bondTwoMonomers(page, peptide1, peptide2); + await bondTwoMonomers( + page, + peptide1, + peptide2, + undefined, + undefined, + false, + false, + ); }); test('"Connect" button is active', async ({ page }) => { @@ -62,10 +70,6 @@ test.describe('Modal window', () => { */ // Create bonds between peptides - await bondTwoMonomers(page, peptide1, peptide2); - - // Chose attachment points - await page.locator('button[title=R1]').nth(0).click(); - await page.locator('button[title=R2]').nth(1).click(); + await bondTwoMonomers(page, peptide1, peptide2, 'R1', 'R2', true, false); }); }); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-hover.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-hover.spec.ts index 6c4ff1b3f1..602f1040db 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-hover.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-hover.spec.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, selectSingleBondTool, waitForPageInit, takeEditorScreenshot, @@ -20,7 +20,7 @@ test.describe('Check attachment point hover', () => { const MONOMER_NAME = 'Tza___3-thiazolylalanine'; const MONOMER_ALIAS = 'Tza'; const coordinatesStart = { x: 300, y: 300 }; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -29,7 +29,7 @@ test.describe('Check attachment point hover', () => { 0, ); const coordinatesEnd = { x: 400, y: 400 }; - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-rotation.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-rotation.spec.ts index c706478747..c681e164b8 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-rotation.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/attachment-point-rotation.spec.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, dragMouseTo, selectRectangleSelectionTool, selectSingleBondTool, @@ -28,7 +28,7 @@ test.describe('Check attachment point rotation', () => { const MONOMER_ALIAS = 'Tza'; // Get 4 peptides locators - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -36,7 +36,7 @@ test.describe('Check attachment point rotation', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -44,7 +44,7 @@ test.describe('Check attachment point rotation', () => { 400, 1, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -52,7 +52,7 @@ test.describe('Check attachment point rotation', () => { 500, 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -98,7 +98,7 @@ test.describe('Check attachment point rotation', () => { const MONOMER_ALIAS = 'Tza'; // Get 4 peptides locators - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -106,7 +106,7 @@ test.describe('Check attachment point rotation', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/polymer-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/polymer-bond-tool.spec.ts index 3886302de8..009ad1ce72 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/polymer-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/polymer-bond-tool.spec.ts @@ -3,7 +3,7 @@ import { selectSingleBondTool, waitForPageInit, takeEditorScreenshot, - addMonomerToCanvas, + addSingleMonomerToCanvas, } from '@utils'; import { hideMonomerPreview, @@ -31,7 +31,7 @@ test.describe('Polymer Bond Tool', () => { const MONOMER_NAME = 'Tza___3-thiazolylalanine'; const MONOMER_ALIAS = 'Tza'; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -39,7 +39,7 @@ test.describe('Polymer Bond Tool', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -47,7 +47,7 @@ test.describe('Polymer Bond Tool', () => { 400, 1, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -55,7 +55,7 @@ test.describe('Polymer Bond Tool', () => { 500, 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -126,7 +126,7 @@ test.describe('Signle Bond Tool', () => { */ const MONOMER_NAME = 'Tza___3-thiazolylalanine'; const MONOMER_ALIAS = 'Tza'; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, @@ -134,7 +134,7 @@ test.describe('Signle Bond Tool', () => { 300, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME, MONOMER_ALIAS, diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts index 850dd799b1..a62ce5d19f 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts @@ -1,6 +1,6 @@ import { Page, test, expect } from '@playwright/test'; import { - addMonomerToCanvas, + addSingleMonomerToCanvas, addRnaPresetOnCanvas, clickRedo, clickUndo, @@ -8,6 +8,7 @@ import { selectSnakeBondTool, takeEditorScreenshot, waitForPageInit, + addBondedMonomersToCanvas, } from '@utils'; import { turnOnMacromoleculesEditor } from '@utils/macromolecules'; import { bondTwoMonomers } from '@utils/macromolecules/polymerBond'; @@ -22,7 +23,7 @@ async function createBondedMonomers(page: Page) { const MONOMER_NAME_MEC = 'meC___N-Methyl-Cysteine'; const MONOMER_ALIAS_MEC = 'meC'; - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME_DSEC, MONOMER_ALIAS_DSEC, @@ -31,24 +32,18 @@ async function createBondedMonomers(page: Page) { 0, ); - const peptide2 = await addMonomerToCanvas( + const [peptide2, peptide3] = await addBondedMonomersToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, 100, 100, - 0, - ); - const peptide3 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 150, - 150, - 1, + 50, + 50, + 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME_MEC, MONOMER_ALIAS_MEC, @@ -60,7 +55,6 @@ async function createBondedMonomers(page: Page) { await selectSingleBondTool(page); await bondTwoMonomers(page, peptide1, peptide2); - await bondTwoMonomers(page, peptide2, peptide3); await bondTwoMonomers(page, peptide3, peptide4); } @@ -77,24 +71,17 @@ test.describe('Snake Bond Tool', () => { */ await selectSnakeBondTool(page); - - const peptide1 = await addMonomerToCanvas( + const [, peptide2] = await addBondedMonomersToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, 300, 300, - 0, - ); - const peptide2 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 400, - 400, - 1, + 100, + 100, + 2, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -102,7 +89,7 @@ test.describe('Snake Bond Tool', () => { 500, 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -113,11 +100,10 @@ test.describe('Snake Bond Tool', () => { await selectSingleBondTool(page); - await bondTwoMonomers(page, peptide1, peptide2); await bondTwoMonomers(page, peptide2, peptide3); await bondTwoMonomers(page, peptide3, peptide4); - await takeEditorScreenshot(page); + // await takeEditorScreenshot(page); }); test('Check snake mode arrange for peptides chain', async ({ page }) => { @@ -126,117 +112,16 @@ test.describe('Snake Bond Tool', () => { Description: Snake bond tool */ - const peptide1 = await addMonomerToCanvas( + await addBondedMonomersToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, 100, 100, - 0, - ); - const peptide2 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 150, - 150, - 1, - ); - const peptide3 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 200, - 200, - 2, - ); - const peptide4 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 250, - 250, - 3, + 50, + 50, + 12, ); - const peptide5 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 300, - 300, - 4, - ); - const peptide6 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 350, - 350, - 5, - ); - const peptide7 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 400, - 400, - 6, - ); - const peptide8 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 450, - 450, - 7, - ); - const peptide9 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 500, - 500, - 8, - ); - const peptide10 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 550, - 550, - 9, - ); - - const peptide11 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 600, - 600, - 10, - ); - const peptide12 = await addMonomerToCanvas( - page, - MONOMER_NAME_TZA, - MONOMER_ALIAS_TZA, - 650, - 650, - 11, - ); - - await selectSingleBondTool(page); - - await bondTwoMonomers(page, peptide1, peptide2); - await bondTwoMonomers(page, peptide2, peptide3); - await bondTwoMonomers(page, peptide3, peptide4); - await bondTwoMonomers(page, peptide4, peptide5); - await bondTwoMonomers(page, peptide5, peptide6); - await bondTwoMonomers(page, peptide6, peptide7); - await bondTwoMonomers(page, peptide7, peptide8); - await bondTwoMonomers(page, peptide8, peptide9); - await bondTwoMonomers(page, peptide9, peptide10); - await bondTwoMonomers(page, peptide10, peptide11); - await bondTwoMonomers(page, peptide11, peptide12); await selectSnakeBondTool(page); @@ -366,7 +251,7 @@ test.describe('Snake Bond Tool', () => { test('Create snake bond for mix chains with nucleotides and peptides', async ({ page, }) => { - const peptide1 = await addMonomerToCanvas( + const peptide1 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -374,7 +259,7 @@ test.describe('Snake Bond Tool', () => { 500, 0, ); - const peptide2 = await addMonomerToCanvas( + const peptide2 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -383,7 +268,7 @@ test.describe('Snake Bond Tool', () => { 1, ); - const peptide3 = await addMonomerToCanvas( + const peptide3 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -392,7 +277,7 @@ test.describe('Snake Bond Tool', () => { 2, ); - const peptide4 = await addMonomerToCanvas( + const peptide4 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -400,7 +285,7 @@ test.describe('Snake Bond Tool', () => { 500, 3, ); - const peptide5 = await addMonomerToCanvas( + const peptide5 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -408,7 +293,7 @@ test.describe('Snake Bond Tool', () => { 550, 4, ); - const peptide6 = await addMonomerToCanvas( + const peptide6 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -416,7 +301,7 @@ test.describe('Snake Bond Tool', () => { 600, 5, ); - const peptide7 = await addMonomerToCanvas( + const peptide7 = await addSingleMonomerToCanvas( page, MONOMER_NAME_TZA, MONOMER_ALIAS_TZA, @@ -495,7 +380,7 @@ test.describe('Snake Bond Tool', () => { ); await page.getByTestId('summary-Sugars').click(); - const sugarOfNucleoside = await addMonomerToCanvas( + const sugarOfNucleoside = await addSingleMonomerToCanvas( page, 'R___Ribose', 'R', @@ -504,7 +389,7 @@ test.describe('Snake Bond Tool', () => { 2, ); await page.getByTestId('summary-Bases').click(); - const baseOfNucleoside = await addMonomerToCanvas( + const baseOfNucleoside = await addSingleMonomerToCanvas( page, 'A___Adenine', 'A', @@ -527,11 +412,13 @@ test.describe('Snake Bond Tool', () => { await takeEditorScreenshot(page); }); - test('Create snake bond for chain with side chains', async ({ page }) => { + test.only('Create snake bond for chain with side chains', async ({ + page, + }) => { await page.getByText('RNA').click(); const { phosphate } = await addRnaPresetOnCanvas( page, - 'A_A_R_P', + 'C_C_R_P', 200, 200, 0, @@ -555,7 +442,7 @@ test.describe('Snake Bond Tool', () => { ); await addRnaPresetOnCanvas(page, 'U_U_R_P', 900, 300, 3, 3); await page.getByTestId('summary-Sugars').click(); - const sugarOfNucleoside = await addMonomerToCanvas( + const sugarOfNucleoside = await addSingleMonomerToCanvas( page, 'R___Ribose', 'R', @@ -564,7 +451,7 @@ test.describe('Snake Bond Tool', () => { 4, ); await page.getByTestId('summary-Bases').click(); - const baseOfNucleoside = await addMonomerToCanvas( + const baseOfNucleoside = await addSingleMonomerToCanvas( page, 'nC6n8A___6-Aminohexyl-8-aminoadenine', 'nC6n8A', @@ -574,88 +461,57 @@ test.describe('Snake Bond Tool', () => { ); await page.getByTestId('PEPTIDES-TAB').click(); - - const monomer1 = await addMonomerToCanvas( + const [peptide] = await addBondedMonomersToCanvas( page, 'A___Alanine', 'A', 500, 500, - 1, + 50, + 50, + 3, ); - const monomer2 = await addMonomerToCanvas( + + const [hcyPeptide, hcyPeptide1] = await addBondedMonomersToCanvas( page, 'Hcy___homocysteine', 'Hcy', - 550, - 550, - 0, - ); - const monomer3 = await addMonomerToCanvas( - page, - 'A___Alanine', - 'A', - 600, 600, + 500, + 50, + 0, 2, ); - const monomer4 = await addMonomerToCanvas( - page, - 'A___Alanine', - 'A', - 650, - 650, - 3, - ); - const monomer5 = await addMonomerToCanvas( - page, - 'A___Alanine', - 'A', - 700, - 700, - 4, - ); - const monomer6 = await addMonomerToCanvas( + + const [balPeptide] = await addBondedMonomersToCanvas( page, 'Bal___beta-Alanine', 'Bal', - 600, - 500, + 700, + 700, + 50, 0, + 2, ); - const monomer7 = await addMonomerToCanvas( + const balPeptide1 = await addSingleMonomerToCanvas( page, 'Bal___beta-Alanine', 'Bal', + 850, 650, - 500, - 1, - ); - const monomer8 = await addMonomerToCanvas( - page, - 'Bal___beta-Alanine', - 'Bal', - 750, - 500, 2, ); await selectSingleBondTool(page); await bondTwoMonomers(page, sugarOfNucleoside, baseOfNucleoside); - await bondTwoMonomers(page, baseOfNucleoside, monomer1, 'R2', 'R1'); - - await bondTwoMonomers(page, monomer1, monomer2); - await bondTwoMonomers(page, monomer2, monomer3); - await bondTwoMonomers(page, monomer3, monomer4); - await bondTwoMonomers(page, monomer2, monomer5, undefined, 'R1'); + await bondTwoMonomers(page, baseOfNucleoside, peptide, 'R2', 'R1'); await bondTwoMonomers(page, phosphate, sugarOfNucleoside); await bondTwoMonomers(page, sugarOfNucleoside, sugar1); await bondTwoMonomers(page, phosphate1, sugar2); - await bondTwoMonomers(page, phosphate2, monomer6, undefined, 'R1'); - await bondTwoMonomers(page, monomer6, monomer7); - await bondTwoMonomers(page, monomer7, monomer8); - + await bondTwoMonomers(page, phosphate2, hcyPeptide, undefined, 'R1'); + await bondTwoMonomers(page, hcyPeptide1, balPeptide); + await bondTwoMonomers(page, hcyPeptide1, balPeptide1, undefined, 'R1'); await takeEditorScreenshot(page); await selectSnakeBondTool(page); diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-1-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-chain-with-side-chains-1-chromium-linux.png index e53f893234b51fc2e26f97c1a9dca4949e8b92fd..deffcbb09248397cd72c623bbf7c157c781e4755 100644 GIT binary patch literal 31822 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 literal 29147 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 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-bond-for-mix-chains-with-nucleotides-and-peptides-2-chromium-linux.png index 29e076e9022cacb35c89efd3bc7639ca4eb5ea0f..b56025d9a8192dd401c0344ac59a2be8499c4f70 100644 GIT binary patch literal 22195 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 literal 23313 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 LHAC#bZ$|$Yi{Y+W literal 22251 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 E1K(ewwg3PC literal 0 HcmV?d00001 diff --git a/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-mode-for-single-monomer-and-nucleoside-2-chromium-linux.png b/ketcher-autotests/tests/Macromolecule-editor/Polymer-Bond-Tool/snake-bond-tool.spec.ts-snapshots/Snake-Bond-Tool-Create-snake-mode-for-single-monomer-and-nucleoside-2-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..89cea56f7907d8113de63a51ff24c2ff87d6b390 GIT binary patch literal 7406 zcmeHKdtB0I+ox<RcJdG+B_QM>Qv{EQBFKA#?f>`ldEe)sefsAIzu$e`*Wr6z_xHN5 zj2{krn}4|RLkI+7e&9RLqY#J*8vzK-^omGq@%0DfjCoQAH(_*G*8h4Uv&$ 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 M|F9=x@3CM02N@Mqo&W#< literal 0 HcmV?d00001