Skip to content

Commit

Permalink
Merge 16ae70c into 212b9ca
Browse files Browse the repository at this point in the history
  • Loading branch information
albertms10 committed Jun 3, 2023
2 parents 212b9ca + 16ae70c commit 9013cde
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 111 deletions.
22 changes: 21 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
{
"cSpell.ignoreWords": ["music"],
"cSpell.words": ["cryptogrammatic", "latin"]
"cSpell.words": [
"Abegg",
"Alain",
"arnold",
"asch",
"cryptogrammatic",
"dmitri",
"edvard",
"Ferrarie",
"franz",
"gustav",
"hercules",
"jehan",
"johann",
"joseph",
"latin",
"niels",
"paul",
"robert",
"Schostakowitsch"
]
}
25 changes: 15 additions & 10 deletions lib/model/cryptogram_scheme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,40 +162,45 @@ class CryptogramScheme {
CryptogramScheme.frenchVariant(),
CryptogramScheme.german(),
];
}

extension CryptogramStringExtension on String {
/// Returns the cryptogrammatic sequence of [Note]s, a sequence which can be
/// taken to refer to an extra-musical text by some 'logical' relationship,
/// usually between note names and letters.
///
/// Example:
/// ```dart
/// 'Bach'.toCryptogram(CryptogramScheme.german())
/// const CryptogramScheme.german().cryptogramOf('Bach')
/// == [Note.b.flat, Note.a, Note.c, Note.b]
///
/// 'Alain'.toCryptogram(CryptogramScheme.frenchVariant())
/// const CryptogramScheme.frenchVariant().cryptogramOf('Alain')
/// == [Note.a, Note.d, Note.a, Note.a, Note.f]
/// ```
List<Note> toCryptogram([
CryptogramScheme scheme = const CryptogramScheme.solmization(),
]) {
List<Note> cryptogramOf(String name) {
final seenMatches = <Match>[];
final notes = SplayTreeMap<int, Note>();

for (final pattern in scheme.patterns.keys) {
final matches = RegExp(pattern, caseSensitive: false).allMatches(this);
for (final pattern in patterns.keys) {
final matches = RegExp(pattern, caseSensitive: false).allMatches(name);
for (final match in matches) {
final isMatchSeen = seenMatches.any(
(element) => match.start >= element.start && match.end <= element.end,
);
if (!isMatchSeen) {
seenMatches.add(match);
notes[match.start] = scheme.patterns[pattern]!;
notes[match.start] = patterns[pattern]!;
}
}
}

return notes.values.toList();
}

@override
bool operator ==(Object other) =>
other is CryptogramScheme &&
name == other.name &&
patterns == other.patterns;

@override
int get hashCode => Object.hash(name, patterns);
}
10 changes: 9 additions & 1 deletion lib/model/name.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import 'package:music_notes/music_notes.dart';
import 'package:note_names/model/alphabet.dart';
import 'package:note_names/model/cryptogram_scheme.dart';

class Name {
final String name;
final Alphabet alphabet;
final CryptogramScheme scheme;

const Name(
this.name, {
this.alphabet = const Alphabet.latinNaturalOrder1(),
this.scheme = const CryptogramScheme.german(),
});

int get numericValue => alphabet.numericValueOfName(name);

Name copyWith({String? name, Alphabet? alphabet}) => Name(
List<Note> get musicalCryptogram => scheme.cryptogramOf(name);

Name copyWith({String? name, Alphabet? alphabet, CryptogramScheme? scheme}) =>
Name(
name ?? this.name,
alphabet: alphabet ?? this.alphabet,
scheme: scheme ?? this.scheme,
);

@override
Expand Down
116 changes: 116 additions & 0 deletions test/model/cryptogram_scheme_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:music_notes/music_notes.dart';
import 'package:note_names/model/cryptogram_scheme.dart';

void main() {
group('CryptogramScheme', () {
group('.schemes', () {
test('should be a list of CryptogramSchemes', () {
expect(
CryptogramScheme.schemes,
const TypeMatcher<List<CryptogramScheme>>(),
);
});
});

group('.cryptogramOf()', () {
test('should return the musical cryptogram of name', () {
final herculesDuxFerrarie = const CryptogramScheme.solmization()
.cryptogramOf('Hercules Dux Ferrarie');
expect(
herculesDuxFerrarie,
[Note.d, Note.c, Note.d, Note.c, Note.d, Note.f, Note.e, Note.d],
);

final arnoldSchonberg =
const CryptogramScheme.german().cryptogramOf('A. SCHBEG');
expect(
arnoldSchonberg,
[Note.a, Note.e.flat, Note.c, Note.b, Note.b.flat, Note.e, Note.g],
);

final belaBartok =
const CryptogramScheme.french().cryptogramOf('BE BA');
expect(belaBartok, [Note.b, Note.e, Note.b, Note.a]);

final carlPhilipEmmanuelBach =
const CryptogramScheme.german().cryptogramOf('CFE BACH');
expect(
carlPhilipEmmanuelBach,
[Note.c, Note.f, Note.e, Note.b.flat, Note.a, Note.c, Note.b],
);

final dmitriSchostakowitsch =
const CryptogramScheme.german().cryptogramOf('D. SCH');
expect(dmitriSchostakowitsch, [Note.d, Note.e.flat, Note.c, Note.b]);

final edvardGrieg = const CryptogramScheme.french().cryptogramOf('EBG');
expect(edvardGrieg, [Note.e, Note.b, Note.g]);

final franzSchubert =
const CryptogramScheme.german().cryptogramOf('F. SCH');
expect(franzSchubert, [Note.f, Note.e.flat, Note.c, Note.b]);

final gustavHolst =
const CryptogramScheme.german().cryptogramOf('GSAH');
expect(gustavHolst, [Note.g, Note.e.flat, Note.a, Note.b]);

final jehanAlain =
const CryptogramScheme.frenchVariant().cryptogramOf('ALAIN');
expect(jehanAlain, [Note.a, Note.d, Note.a, Note.a, Note.f]);

final johannesBrahms =
const CryptogramScheme.german().cryptogramOf('BAHS');
expect(johannesBrahms, [Note.b.flat, Note.a, Note.b, Note.e.flat]);

final johannSebastianBach =
const CryptogramScheme.german().cryptogramOf('BACH');
expect(johannSebastianBach, [Note.b.flat, Note.a, Note.c, Note.b]);

final johnCage = const CryptogramScheme.german().cryptogramOf('CAGE');
expect(johnCage, [Note.c, Note.a, Note.g, Note.e]);

final josephHaydn =
const CryptogramScheme.german().cryptogramOf('HAYDN');
expect(josephHaydn, [Note.b, Note.a, Note.d, Note.d, Note.g]);

final metaAbegg = const CryptogramScheme.german().cryptogramOf('ABEGG');
expect(metaAbegg, [Note.a, Note.b.flat, Note.e, Note.g, Note.g]);

final nielsGade = const CryptogramScheme.german().cryptogramOf('GADE');
expect(nielsGade, [Note.g, Note.a, Note.d, Note.e]);

final paulSacher =
const CryptogramScheme.german().cryptogramOf('SACHER');
expect(
paulSacher,
[Note.e.flat, Note.a, Note.c, Note.b, Note.e, Note.d],
);

final robertSchumann =
const CryptogramScheme.german().cryptogramOf('SCHA');
expect(robertSchumann, [Note.e.flat, Note.c, Note.b, Note.a]);

final asch1 = const CryptogramScheme.german().cryptogramOf('ASCH');
expect(asch1, [Note.a.flat, Note.c, Note.b]);

final asch2 = const CryptogramScheme.german().cryptogramOf('A SCH');
expect(asch2, [Note.a, Note.e.flat, Note.c, Note.b]);
});
});

group('.hashCode', () {
test('should remove duplicates in a Set', () {
final collection = {
// ignore: prefer_const_constructors
CryptogramScheme.french(),
// ignore: prefer_const_constructors
CryptogramScheme.frenchVariant(),
// ignore: prefer_const_constructors
CryptogramScheme.french(),
};
expect(collection.length, 2);
});
});
});
}
92 changes: 0 additions & 92 deletions test/model/cryptogram_string_extension_test.dart

This file was deleted.

5 changes: 2 additions & 3 deletions test/model/main.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'alphabet_test.dart' as alphabet_test;
import 'cryptogram_string_extension_test.dart'
as cryptogram_string_extension_test;
import 'cryptogram_scheme_test.dart' as cryptogram_scheme_test;
import 'name_test.dart' as name_test;

void main() {
alphabet_test.main();
cryptogram_string_extension_test.main();
cryptogram_scheme_test.main();
name_test.main();
}
21 changes: 17 additions & 4 deletions test/model/name_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:music_notes/music_notes.dart';
import 'package:note_names/model/alphabet.dart';
import 'package:note_names/model/cryptogram_scheme.dart';
import 'package:note_names/model/name.dart';

void main() {
Expand All @@ -17,7 +19,7 @@ void main() {
});

group('.numericValue', () {
test('should return the numeric value of this name', () {
test('should return the numeric value of this Name', () {
expect(const Name('ABC').numericValue, 6);

const alphabet = Alphabet(
Expand All @@ -28,6 +30,15 @@ void main() {
});
});

group('.musicalCryptogram', () {
test('should return the musical cryptogram of this Name', () {
expect(
const Name('Bach').musicalCryptogram,
[Note.b.flat, Note.a, Note.c, Note.b],
);
});
});

group('.copyWith', () {
test('should return a new copy of this Name', () {
const name = Name('ABC');
Expand All @@ -37,15 +48,17 @@ void main() {
});

test(
'should return a new copy of this SingleBooking with overridden '
'properties',
'should return a new copy of this Name with overridden properties',
() {
const alphabet =
Alphabet(name: 'Alphabet 1', letterToNumber: {'Z': 24});
const scheme = CryptogramScheme.french();
const name = Name('ABC');
final copiedName = name.copyWith(name: 'Z', alphabet: alphabet);
final copiedName =
name.copyWith(name: 'Z', alphabet: alphabet, scheme: scheme);
expect(copiedName.name, 'Z');
expect(copiedName.alphabet, alphabet);
expect(copiedName.scheme, scheme);
},
);
});
Expand Down

0 comments on commit 9013cde

Please sign in to comment.