import { PositionKind, SemanticPosition, Facing, BalanceWeight, handsInLine, CircleSide, handsInLongLines } from "../interpreterCommon.js"; import { SemanticAnimationKind } from "../lowLevelMove.js"; import { Hand } from "../rendererConstants.js"; import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js"; const moveName = "Rory O'More"; class RoryOMoreSingleVariant extends SingleVariantMoveInterpreter { moveAsLowLevelMoves(): LowLevelMovesForAllDancers { // TODO Could be in long or short lines. return this.handleMove(({ startPos }) => { const startingPos: SemanticPosition = { ...startPos, hands: handsInLine({ wavy: true, which: startPos.which, facing: startPos.facing }) }; let endPos: SemanticPosition; if (startPos.kind === PositionKind.ShortLines) { if (startPos.facing !== Facing.Up && startPos.facing !== Facing.Down) { throw new Error("To be in short wavy lines, must be facing up or down, not " + startPos.facing); } const { newPos: endWhich, wrap } = startPos.which.shiftWithWrap(this.moveInterpreter.dir, startPos.facing); const endLineOffset = !wrap ? startPos.lineOffset : (startPos.lineOffset ?? 0) + wrap; if (wrap) { startingPos.hands = handsInLongLines(true) } endPos = { ...startPos, which: endWhich, hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }), lineOffset: endLineOffset, }; } else { if (startPos.facing !== Facing.Left && startPos.facing !== Facing.Right) { throw new Error("To be in long wavy lines, must be facing left or right, not " + startPos.facing); } const endWhich = startPos.which.swapUpAndDown(); const sideTowards = (startPos.facing === Facing.Right) === (this.moveInterpreter.dir === Hand.Left) ? CircleSide.Bottom : CircleSide.Top; const endSetOffset = sideTowards === endWhich.topBottomSide() ? startPos.setOffset : (startPos.setOffset ?? 0) + (sideTowards === CircleSide.Bottom ? +1 : -1); endPos = { ...startPos, which: endWhich, hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }), setOffset: endSetOffset, }; } const maybeBalance: PartialLowLevelMove[] = (this.move.parameters.bal ? [ { beats: this.moveInterpreter.balPartBeats, endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Left : BalanceWeight.Right }, movementPattern: { kind: SemanticAnimationKind.Linear }, }, { beats: this.moveInterpreter.balPartBeats, endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Right : BalanceWeight.Left }, movementPattern: { kind: SemanticAnimationKind.Linear }, }, ] : []); return this.combine([...maybeBalance, { beats: this.moveInterpreter.roryBeats, endPosition: endPos, movementPattern: { kind: SemanticAnimationKind.Linear, minRotation: this.moveInterpreter.dir === Hand.Right ? +360 : -360, handsDuring: "None", }, } ], startingPos); }); } } class RoryOMore extends MoveInterpreter { public readonly dir: Hand; public readonly balPartBeats: number; public readonly roryBeats: number; constructor(args: MoveInterpreterCtorArgs) { super(args); if (this.move.parameters.who !== "everyone") { throw new Error(this.move.move + " that doesn't include everyone is unsupported."); } this.dir = this.move.parameters.slide ? Hand.Left : Hand.Right; const balBeats = this.move.parameters.bal ? this.move.beats / 2 : 0; this.balPartBeats = balBeats / 2; this.roryBeats = this.move.beats - balBeats; } buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter { return new RoryOMoreSingleVariant(this, startingPos); } } moveInterpreters.set(moveName, RoryOMore);