package com.xenoage.zong.musiclayout.notator.chord.accidentals; import static com.xenoage.utils.collections.CollectionUtils.alist; import static com.xenoage.utils.collections.CollectionUtils.alistFromLists; import static com.xenoage.utils.kernel.Range.range; import static com.xenoage.utils.math.Fraction._1$4; import static com.xenoage.zong.core.music.Pitch.pi; import static com.xenoage.zong.core.position.MP.atElement; import static com.xenoage.zong.core.position.MP.mp0; import static com.xenoage.zong.core.text.FormattedTextStyle.defaultStyle; import static com.xenoage.zong.core.text.FormattedTextUtils.styleText; import static com.xenoage.zong.musiclayout.notator.chord.accidentals.OneAccidental.oneAccidental; import static com.xenoage.zong.musiclayout.notator.chord.accidentals.Strategy.getParams; import static com.xenoage.zong.musiclayout.notator.chord.accidentals.TestData.contextC; import static com.xenoage.zong.musiclayout.notator.chord.accidentals.ThreeAccidentals.threeAccidentals; import static com.xenoage.zong.musiclayout.notator.chord.accidentals.TwoAccidentals.twoAccidentals; import static com.xenoage.zong.musiclayout.settings.ChordWidths.defaultChordWidthsNormal; import static material.ExampleResult.perfect; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.List; import java.util.Map; import org.junit.Test; import com.xenoage.utils.font.FontInfo; import com.xenoage.utils.font.FontStyle; import com.xenoage.zong.core.Score; import com.xenoage.zong.core.ScoreFactory; import com.xenoage.zong.core.music.ColumnElement; import com.xenoage.zong.core.music.MeasureElement; import com.xenoage.zong.core.music.Pitch; import com.xenoage.zong.core.music.chord.Chord; import com.xenoage.zong.core.music.chord.ChordFactory; import com.xenoage.zong.core.music.direction.Words; import com.xenoage.zong.core.music.key.TraditionalKey; import com.xenoage.zong.core.music.rest.Rest; import com.xenoage.zong.core.music.time.TimeSignature; import com.xenoage.zong.core.music.time.TimeType; import com.xenoage.zong.core.text.FormattedTextStyle; import com.xenoage.zong.io.selection.Cursor; import com.xenoage.zong.musiclayout.notation.chord.AccidentalsNotation; import com.xenoage.zong.musiclayout.settings.ChordWidths; import com.xenoage.zong.test.VisualTest; import com.xenoage.zong.test.VisualTester; import material.ExampleResult; import material.ExampleResult.Result; import material.accidentals.Example; import material.accidentals.OneAccidental; import material.accidentals.RossThreeAccidentals; import material.accidentals.RossTwoAccidentals; /** * Tests for {@link Strategy}. * * @author Andreas Wenger */ public class StrategyTest implements VisualTest { private Strategy[] testees = { null, oneAccidental, twoAccidentals, threeAccidentals }; private final ChordWidths cw = defaultChordWidthsNormal; private List<Example> getAllExamples() { return alistFromLists(new OneAccidental().getExamples(), new RossTwoAccidentals().getExamples(), new RossThreeAccidentals().getExamples()); } @Test public void testStrategies() { //collect test material List<Example> examples = getAllExamples(); //run tests List<ExampleResult> failedExamples = alist(); for (Example example : examples) { ExampleResult result = testExample(example); if (result.getResult() == Result.Failed) failedExamples.add(result); } //list failed examples if (failedExamples.size() > 0) { for (ExampleResult example : failedExamples) System.out.println(example.getExample().getName() + " failed: " + example.getComment()); fail(failedExamples.size() + " of " + examples.size() + " examples failed. " + "See console for details."); } } private ExampleResult testExample(Example example) { int accsCount = example.getAccsCount(); AccidentalsNotation accs = testees[accsCount].compute(getParams(example.getPitches(), example.getNotes(), example.getAccsCount(), cw, example.getContext())); ExampleResult result = perfect(example); result.checkEquals("number of accidentals", accsCount, accs.accidentals.length); result.checkEquals("total width", example.getExpectedAccsWidthIs(), accs.widthIs); float[] accsXIs = example.getExpectedAccsXIs(); if (accsXIs != null) { for (int i : range(accsCount)) { result.checkEquals("offset of accidental " + i, accsXIs[i], accs.accidentals[i].xIs); } } int[] accsLp = example.getExpectedAccsLp(); for (int i : range(accsCount)) { result.checkEquals("LP of accidental " + i, accsLp[i], accs.accidentals[i].yLp); } return result; } @Test public void getAccNoteIndexTest() { //C#5 //must have an accidental List<Pitch> pitches = alist(pi(0, 1, 5)); assertEquals(0, Strategy.getAccNoteIndex(pitches, 0, contextC)); //E4, G#4, C#5 (no accidental at bottom note) //must have accidentals on note 1 and 2 pitches = alist(pi(2, 0, 4), pi(4, 1, 4), pi(0, 1, 5)); assertEquals(1, Strategy.getAccNoteIndex(pitches, 0, contextC)); assertEquals(2, Strategy.getAccNoteIndex(pitches, 2, contextC)); } @Override public Score getScore() { //collect test material List<Example> examples = getAllExamples(); //text style FormattedTextStyle style = defaultStyle.withFont(new FontInfo("Arial", 6f, FontStyle.normal)); //one chord in each measure Score score = ScoreFactory.create1Staff(); Cursor cursor = new Cursor(score, mp0, true); cursor.write(new TimeSignature(TimeType.time_3_4)); for (int i : range(examples)) { Example example = examples.get(i); cursor.setMp(atElement(0, i, 0, 0)); //write key int fifths = ((TraditionalKey) example.getContext().getKey()).getFifths(); cursor.write((ColumnElement) new TraditionalKey(fifths)); //write example name (each 2nd example one line down for better reading) String text = (i % 2 == 1 ? "\n" : "") + example.getName(); cursor.write((MeasureElement) new Words(styleText(text, style))); //write chord with all accidentals from context (or a rest) Map<Pitch, Integer> accs = example.getContext().getAccidentals(); if (accs.size() > 0) { Pitch[] pitches = new Pitch[accs.size()]; int accIndex = 0; for (Pitch acc : accs.keySet()) { pitches[accIndex] = pi(acc.getStep(), accs.get(acc), acc.getOctave()); accIndex++; } Chord accsChords = ChordFactory.chord(pitches, _1$4); cursor.write(accsChords); } else { cursor.write(new Rest(_1$4)); } //write a rest cursor.write(new Rest(_1$4)); //write the tested chord Chord testedChord = ChordFactory.chord(example.getPitches().toArray(new Pitch[0]), _1$4); cursor.write(testedChord); } return score; } public static void main(String... args) { VisualTester.start(new StrategyTest()); } }