import { Facing, ShortLinesPosition, PositionKind, CirclePosition, SemanticPosition, HandConnection, HandTo, handsInCircle } from "../interpreterCommon.js"; import { Move } from "../libfigureMapper.js"; import { SemanticAnimationKind } from "../lowLevelMove.js"; import { Hand } from "../rendererConstants.js"; import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js"; const moveName: Move["move"] = "up the hall"; // TODO Share implementation between up/down the hall? class UpTheHallSingleVariant extends SingleVariantMoveInterpreter { moveAsLowLevelMoves(): LowLevelMovesForAllDancers { if (this.move.parameters.who !== "everyone") { throw new Error("Don't know what it means for not everyone to go up the hall."); } if (this.move.parameters.moving !== "all") { throw new Error("Not sure what it means for not all to be moving in up the hall."); } if (this.move.parameters.ender !== "circle") { throw new Error("Unsupported up the hall ender: " + this.move.parameters.ender); } if (this.move.parameters.facing !== "forward") { throw new Error("Unsupported up the hall facing: " + this.move.parameters.facing); } return this.handleMove(({ startPos }) => { const startFacing = this.move.parameters.facing === "backward" ? Facing.Down : Facing.Up; const startWhich: ShortLinesPosition = startPos.kind === PositionKind.ShortLines ? startPos.which // TODO Is this always the right way to convert circle to short lines? // (Does it even matter except for dance starting formations?) : new Map([ [CirclePosition.TopLeft, ShortLinesPosition.MiddleLeft], [CirclePosition.BottomLeft, ShortLinesPosition.FarLeft], [CirclePosition.BottomRight, ShortLinesPosition.FarRight], [CirclePosition.TopRight, ShortLinesPosition.MiddleRight], ]).get(startPos.which)!; const startingPos: SemanticPosition & { kind: PositionKind.ShortLines, setOffset: number } = { kind: PositionKind.ShortLines, facing: startFacing, which: startWhich, hands: startWhich.isMiddle() ? new Map([ [Hand.Left, { hand: Hand.Left, to: HandTo.DancerLeft }], [Hand.Right, { hand: Hand.Right, to: HandTo.DancerRight }], ]) : new Map([ startWhich.isLeft() === (this.move.parameters.facing === "backward") ? [Hand.Right, { hand: Hand.Right, to: HandTo.DancerRight }] : [Hand.Left, { hand: Hand.Left, to: HandTo.DancerLeft }] ]), setOffset: startPos.setOffset ?? 0, lineOffset: startPos.lineOffset, }; const endWhich = new Map([ [ShortLinesPosition.FarLeft, CirclePosition.TopLeft], [ShortLinesPosition.MiddleLeft, CirclePosition.BottomLeft], [ShortLinesPosition.MiddleRight, CirclePosition.BottomRight], [ShortLinesPosition.FarRight, CirclePosition.TopRight], ]).get(startWhich)!; const endingPos: SemanticPosition & { kind: PositionKind.Circle } = { kind: PositionKind.Circle, which: endWhich, facing: Facing.CenterOfCircle, setOffset: startingPos.setOffset - 1, lineOffset: startingPos.lineOffset, hands: handsInCircle, } return this.combine([ { beats: 4, endPosition: { ...startingPos, setOffset: startingPos.setOffset - 1 }, movementPattern: { kind: SemanticAnimationKind.Linear }, }, { beats: this.move.beats - 4, endPosition: endingPos, // TODO Is bend the line just linear? movementPattern: { kind: SemanticAnimationKind.Linear, minRotation: startingPos.which.isLeft() ? -1 : +1 }, }], startingPos); }); } } class UpTheHall extends MoveInterpreter { buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter { return new UpTheHallSingleVariant(this, startingPos); } } moveInterpreters.set(moveName, UpTheHall);