@@ -31,17 +31,21 @@ def all_pitches(document):
|
||||
class GuitarPracticeTests(unittest.TestCase):
|
||||
def test_fret_boundaries_and_crossing_twelve(self):
|
||||
self.assertIn(TabPosition(6, 0, 40), positions_for_pitch(Fraction(40)))
|
||||
self.assertIn(TabPosition(1, 15, 79), positions_for_pitch(Fraction(79)))
|
||||
self.assertFalse(positions_for_pitch(Fraction(80)))
|
||||
self.assertIn(TabPosition(1, 20, 84), positions_for_pitch(Fraction(84)))
|
||||
self.assertFalse(positions_for_pitch(Fraction(85)))
|
||||
self.assertFalse(positions_for_pitch(Fraction(129, 2)))
|
||||
self.assertEqual([p.fret for p in positions_for_string(1, 64, tuple(range(12)))], list(range(16)))
|
||||
self.assertEqual([p.fret for p in positions_for_string(1, 64, tuple(range(12)))], list(range(21)))
|
||||
for fret in range(16, 21):
|
||||
self.assertIn(TabPosition(6, fret, 40 + fret), positions_for_pitch(Fraction(40 + fret)))
|
||||
self.assertTrue(within_fret_span((TabPosition(4, 11, 61), TabPosition(3, 12, 67), TabPosition(2, 14, 73))))
|
||||
self.assertTrue(within_fret_span((TabPosition(6, 0, 40), TabPosition(1, 15, 79))))
|
||||
self.assertFalse(within_fret_span((TabPosition(4, 10, 60), TabPosition(1, 15, 79))))
|
||||
content = xml_note('G', extra=technical(1, 15), octave=5)
|
||||
self.assertTrue(within_fret_span((TabPosition(6, 0, 40), TabPosition(1, 20, 84))))
|
||||
self.assertFalse(within_fret_span((TabPosition(4, 10, 60), TabPosition(1, 20, 84))))
|
||||
content = xml_note('C', extra=technical(1, 20), octave=6)
|
||||
validate_guitar_practice(parse(xml_score(content, TAB_STAFF)))
|
||||
with self.assertRaisesRegex(ValueError, '0-15'):
|
||||
validate_guitar_practice(parse(xml_score(xml_note('G', alter=1, extra=technical(1, 16), octave=5), TAB_STAFF)))
|
||||
with self.assertRaisesRegex(ValueError, '0-20'):
|
||||
validate_guitar_practice(parse(xml_score(xml_note('C', alter=1, extra=technical(1, 21), octave=6), TAB_STAFF)))
|
||||
with self.assertRaisesRegex(ValueError, '0-20'):
|
||||
validate_guitar_practice(parse(xml_score(xml_note('D', alter=-1, extra=technical(6, 21)), TAB_STAFF)))
|
||||
def test_arranger_does_not_truncate_candidate_positions(self):
|
||||
def candidates(string, open_midi, pitch_classes):
|
||||
if string == 6:
|
||||
@@ -89,7 +93,7 @@ class GuitarPracticeTests(unittest.TestCase):
|
||||
self.assertEqual(notes(result)[0]['pitches'][0]['letter'], 'c')
|
||||
self.assertEqual(fraction(notes(result)[0]['pitches'][0]['alter']), 2)
|
||||
self.assertEqual(result['staves'][0]['measures'][0]['attributes'][0]['key'], key_from_fifths(1))
|
||||
def test_keyless_reference_required_for_both_practice_types(self):
|
||||
def test_keyless_reference_required_for_practice(self):
|
||||
source = parse(xml_score(xml_note(), '<key><fifths>0</fifths><mode>none</mode></key>'))
|
||||
with self.assertRaisesRegex(ValueError, 'vamp:tonic'):
|
||||
transpose_guitar_practice(source, 'D')
|
||||
@@ -197,31 +201,29 @@ class GuitarPracticeTests(unittest.TestCase):
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
(root / 'data/songs').mkdir(parents=True)
|
||||
source = root / 'data/practice/chord/lesson/wide.xml'
|
||||
source.parent.mkdir(parents=True)
|
||||
source = root / 'data/001.xml'
|
||||
source.parent.mkdir(parents=True, exist_ok=True)
|
||||
source.write_text(xml_score(content), encoding='utf-8')
|
||||
output = root / 'output'
|
||||
output.mkdir()
|
||||
(output / 'last-good').write_text('preserved')
|
||||
args = argparse.Namespace(data_dir=root / 'data', output_dir=output, static_assets_dir=Path('package/assets'), clean=True, check=False)
|
||||
args = argparse.Namespace(data_dir=root / 'data', output_dir=output, static_assets_dir=Path('package/assets'), check=False)
|
||||
with patch('generator.__main__.engrave_tree') as engrave:
|
||||
with self.assertRaisesRegex(ValueError, r'wide.xml, target key C:.*measure 1'):
|
||||
with self.assertRaisesRegex(ValueError, r'001.xml, target key C:.*measure 1'):
|
||||
generate_assets(args)
|
||||
engrave.assert_not_called()
|
||||
self.assertEqual((output / 'last-good').read_text(), 'preserved')
|
||||
self.assertEqual(list(output.iterdir()), [output / 'last-good'])
|
||||
def test_all_practice_types_require_twelve_deterministic_variants(self):
|
||||
def test_practice_requires_twelve_deterministic_variants(self):
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
source, output = Path(temp) / 'source', Path(temp) / 'output'
|
||||
for practice_type in ('chord', 'melody'):
|
||||
path = source / practice_type / '001_lesson' / '001-exercise.xml'
|
||||
path.parent.mkdir(parents=True)
|
||||
path.write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
self.assertEqual(generate_practice_scores(source, output), 24)
|
||||
source.mkdir()
|
||||
(source / '001.xml').write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
self.assertEqual(generate_practice_scores(source, output), 12)
|
||||
validate_practice_variants(output)
|
||||
first = {p.relative_to(output): p.read_bytes() for p in output.rglob('*.json')}
|
||||
generate_practice_scores(source, output)
|
||||
self.assertEqual(first, {p.relative_to(output): p.read_bytes() for p in output.rglob('*.json')})
|
||||
next((output / 'chord').rglob('g.json')).unlink()
|
||||
with self.assertRaisesRegex(ValueError, 'chord practice generator drift'):
|
||||
(output / '001/g.json').unlink()
|
||||
with self.assertRaisesRegex(ValueError, 'practice generator drift'):
|
||||
validate_practice_variants(output)
|
||||
|
||||
Reference in New Issue
Block a user