import { SourceMeasure } from "../../VoiceData/SourceMeasure" ; import { RepetitionInstruction , RepetitionInstructionEnum , AlignmentType } from "../../VoiceData/Instructions/RepetitionInstruction" ; import { RepetitionInstructionComparer } from "../../VoiceData/Instructions/RepetitionInstruction" ; import { ArgumentOutOfRangeException } from "../../Exceptions" ; import { MusicSheet } from "../../MusicSheet" ; export class RepetitionCalculator { private musicSheet : MusicSheet ; private repetitionInstructions : RepetitionInstruction [ ] = [ ] ; private currentMeasure : SourceMeasure ; private currentMeasureIndex : number ; param musicSheet param repetitionInstructions public calculateRepetitions ( musicSheet , repetitionInstructions ) { this . musicSheet = < MusicSheet > musicSheet ; this . repetitionInstructions = repetitionInstructions ; const sourceMeasures = this . musicSheet . SourceMeasures ; for ( let idx = 0 , len = this . repetitionInstructions . length ; idx < len ; ++ idx ) { const instruction = this . repetitionInstructions [ idx ] ; this . currentMeasureIndex = instruction . measureIndex ; this . currentMeasure = sourceMeasures [ this . currentMeasureIndex ] ; this . handleRepetitionInstructions ( instruction ) ; } for ( let idx = 0 , len = this . musicSheet . SourceMeasures . length ; idx < len ; ++ idx ) { const measure = this . musicSheet . SourceMeasures [ idx ] ; if ( measure . FirstRepetitionInstructions . length > 1 ) { measure . FirstRepetitionInstructions . sort ( RepetitionInstructionComparer . Compare ) ; } if ( measure . LastRepetitionInstructions . length > 1 ) { measure . LastRepetitionInstructions . sort ( RepetitionInstructionComparer . Compare ) ; } } } private handleRepetitionInstructions ( currentRepetitionInstruction ) { if ( ! this . currentMeasure ) { return false ; } switch ( currentRepetitionInstruction . type ) { case RepetitionInstructionEnum . StartLine : this . currentMeasure . FirstRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . BackJumpLine : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . Ending : if ( currentRepetitionInstruction . alignment === AlignmentType . Begin ) { this . currentMeasure . FirstRepetitionInstructions . push ( currentRepetitionInstruction ) ; } else { for ( let idx = 0 , len = currentRepetitionInstruction . endingIndices . length ; idx < len ; ++ idx ) { this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; } } break ; case RepetitionInstructionEnum . Segno : this . currentMeasure . FirstRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . Fine : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . ToCoda : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . Coda : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DaCapo : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DalSegno : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DalSegnoAlFine : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DaCapoAlFine : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DalSegnoAlCoda : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . DaCapoAlCoda : this . currentMeasure . LastRepetitionInstructions . push ( currentRepetitionInstruction ) ; break ; case RepetitionInstructionEnum . None : break ; default : throw new ArgumentOutOfRangeException ( "currentRepetitionInstruction" ) ; } return true ; } }