import copy import dataclasses from fractions import Fraction as F import unittest import generator.arrange.generate import generator.arrange.form import generator.model import generator.parts import generator.solo.arrangement from generator.solo import analysis, profiles, placement, types, harmonic from tests.solo_fixtures import song from tests.solo_fixtures import note from tests.solo_fixtures import choices def events(measure): return tuple((generator.model.fraction(n['onset']), generator.model.fraction(n['duration']), tuple((p['letter'],p['alter']['numerator'],p['octave'],p['tablature']['string'],p['tablature']['fret']) for p in n['pitches'])) for v in measure['voices'] for n in v['notes']) class SoloInstrumentAndIdentity(unittest.TestCase): def test_role_ranges_and_no_open_strings(self): acoustic=profiles.for_part('acoustic');electric=profiles.for_part('electric') self.assertEqual(acoustic.register,(41,76));self.assertEqual(electric.register,(41,76)) self.assertTrue(acoustic.permits(41));self.assertTrue(electric.permits(50)) self.assertTrue(acoustic.permits(72)) for profile in (acoustic,electric): for midi in range(40,78): for p in placement.positions(midi,profile): self.assertIn(p.string_number,profile.strings) self.assertTrue(1<=p.fret<=12) self.assertTrue(any(p.string_number==1 for p in placement.positions(65,electric))) self.assertTrue(any(p.string_number==1 for p in placement.positions(65,acoustic))) def test_soft_overlapping_registers_do_not_inherit_a_mandatory_octave(self): source=analysis.analyze(generator.parts.prepare_document(song(count=4,chords=('CM7',)))) acoustic=profiles.for_part('acoustic',source);electric=profiles.for_part('electric',source) self.assertIsNone(electric.reference);self.assertIsNone(acoustic.reference) self.assertEqual(acoustic.melody_range,electric.melody_range)