import { HandConnection, HandTo, BalanceWeight, PositionKind, ShortLinesPosition, SemanticPosition } from "../interpreterCommon.js"; import { SemanticAnimationKind } from "../lowLevelMove.js"; import { Hand } from "../rendererConstants.js"; import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js"; const moveName = "pull by dancers"; class PullByDancersSingleVariant extends SingleVariantMoveInterpreter { moveAsVariants(previousMoveVariant: string): VariantCollection { const res = new Map(); for (const toShortLines of [true, false]) { try { res.set(toShortLines ? "ToShortLines" : "FullPullBy", { lowLevelMoves: this.moveAsLowLevelMovesTo(toShortLines), previousMoveVariant }); } catch { } } return res; } moveAsLowLevelMovesTo(toShortLines: boolean): LowLevelMovesForAllDancers { // TODO Might make sense to think of pull by as not a full swap? // e.g., in Blue and Green Candles, it's treated as only getting to // ShortLinesPosition.Middle* before doing an allemande. return this.handlePairedMove(this.move.parameters.who, ({ startPos, around, withPos }) => { if (toShortLines) { if (startPos.kind !== PositionKind.Circle) { throw new Error("ToShortLines variant of " + this.move.move + " only makes sense starting from a circle."); } } // TODO Adjust facing? const startPosition = { ...startPos, hands: new Map([ [ this.moveInterpreter.hand, { hand: this.moveInterpreter.hand, to: around === "Center" ? HandTo.DiagonalAcrossCircle : HandTo.DancerForward } ]]), facing: startPos.which.facingAcross(), }; const endPos: SemanticPosition = toShortLines ? { ...withPos, hands: undefined, facing: startPosition.facing, kind: PositionKind.ShortLines, which: ShortLinesPosition.fromSide(withPos.which.leftRightSide(), "Middle"), longLines: undefined, // Needed to satisfy type-checker. } : { ...withPos, hands: undefined, facing: startPosition.facing, }; const passBy: PartialLowLevelMove = { beats: this.moveInterpreter.pullBeats, endPosition: endPos, movementPattern: { kind: SemanticAnimationKind.PassBy, around, side: this.moveInterpreter.hand, withHands: true, facing: "Start", otherPath: "Swap", } }; if (this.move.parameters.bal) { return this.combine([ { beats: this.moveInterpreter.balancePartBeats, endPosition: { ...startPosition, balance: BalanceWeight.Forward, }, movementPattern: { kind: SemanticAnimationKind.Linear, } }, { beats: this.moveInterpreter.balancePartBeats, endPosition: { ...startPosition, balance: BalanceWeight.Backward, }, movementPattern: { kind: SemanticAnimationKind.Linear, } }, passBy], startPosition); } else { return this.combine([passBy], startPosition); } }, !toShortLines ? undefined : ({startPos}) => { return this.combine([{ beats: this.move.beats, movementPattern: { kind: SemanticAnimationKind.Linear, }, endPosition: { ...startPos, kind: PositionKind.ShortLines, which: ShortLinesPosition.fromSide(startPos.which.leftRightSide(), "Far"), facing: startPos.which.facingAcross(), hands: undefined, longLines: undefined, } }], startPos); }); } } class PullByDancers extends MoveInterpreter { public readonly hand: Hand; public readonly balancePartBeats: number; public readonly pullBeats: number; constructor(args: MoveInterpreterCtorArgs) { super(args); this.hand = this.move.parameters.hand ? Hand.Right : Hand.Left; const balanceBeats = this.move.parameters.bal ? this.move.beats > 4 ? this.move.beats - 4 : this.move.beats > 2 ? 2 : this.move.beats / 2 : 0; this.balancePartBeats = balanceBeats / 2; this.pullBeats = this.move.beats - balanceBeats; } buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter { return new PullByDancersSingleVariant(this, startingPos); } } moveInterpreters.set(moveName, PullByDancers);