From 7fa04f4e6942e877058a764e4b9c0dfdf5223a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Ma=C3=B1osa?= Date: Sat, 3 Jun 2023 15:52:33 +0200 Subject: [PATCH] refactor(cryptogram_scheme): move `cryptogramOf` method (#11) * refactor(cryptogram_scheme): move `cryptogramOf` method * fix(name): remove redundant argument value * refactor(cryptogram_scheme): fix typos --- .vscode/settings.json | 22 +++- lib/model/cryptogram_scheme.dart | 25 ++-- lib/model/name.dart | 10 +- test/model/cryptogram_scheme_test.dart | 116 ++++++++++++++++++ .../cryptogram_string_extension_test.dart | 92 -------------- test/model/main.dart | 5 +- test/model/name_test.dart | 21 +++- 7 files changed, 180 insertions(+), 111 deletions(-) create mode 100644 test/model/cryptogram_scheme_test.dart delete mode 100644 test/model/cryptogram_string_extension_test.dart diff --git a/.vscode/settings.json b/.vscode/settings.json index 5ff2d1e..cb54036 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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" + ] } diff --git a/lib/model/cryptogram_scheme.dart b/lib/model/cryptogram_scheme.dart index 406d768..10e21c6 100644 --- a/lib/model/cryptogram_scheme.dart +++ b/lib/model/cryptogram_scheme.dart @@ -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 toCryptogram([ - CryptogramScheme scheme = const CryptogramScheme.solmization(), - ]) { + List cryptogramOf(String name) { final seenMatches = []; final notes = SplayTreeMap(); - 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); } diff --git a/lib/model/name.dart b/lib/model/name.dart index 3f37886..646de68 100644 --- a/lib/model/name.dart +++ b/lib/model/name.dart @@ -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 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 diff --git a/test/model/cryptogram_scheme_test.dart b/test/model/cryptogram_scheme_test.dart new file mode 100644 index 0000000..1055257 --- /dev/null +++ b/test/model/cryptogram_scheme_test.dart @@ -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>(), + ); + }); + }); + + 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); + }); + }); + }); +} diff --git a/test/model/cryptogram_string_extension_test.dart b/test/model/cryptogram_string_extension_test.dart deleted file mode 100644 index afeddbc..0000000 --- a/test/model/cryptogram_string_extension_test.dart +++ /dev/null @@ -1,92 +0,0 @@ -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('CryptogramStringExtension', () { - group('.toCryptogram()', () { - test('should return the musical cryptogram of this String', () { - final herculesDuxFerrarie = 'Hercules Dux Ferrarie'.toCryptogram(); - expect( - herculesDuxFerrarie, - [Note.d, Note.c, Note.d, Note.c, Note.d, Note.f, Note.e, Note.d], - ); - - final arnoldSchonberg = - 'A. SCHBEG'.toCryptogram(const CryptogramScheme.german()); - expect( - arnoldSchonberg, - [Note.a, Note.e.flat, Note.c, Note.b, Note.b.flat, Note.e, Note.g], - ); - - final belaBartok = - 'BE BA'.toCryptogram(const CryptogramScheme.french()); - expect(belaBartok, [Note.b, Note.e, Note.b, Note.a]); - - final carlPhilipEmmanuelBach = - 'CFE BACH'.toCryptogram(const CryptogramScheme.german()); - expect( - carlPhilipEmmanuelBach, - [Note.c, Note.f, Note.e, Note.b.flat, Note.a, Note.c, Note.b], - ); - - final dimitriSchostakowitsch = - 'D. SCH'.toCryptogram(const CryptogramScheme.german()); - expect(dimitriSchostakowitsch, [Note.d, Note.e.flat, Note.c, Note.b]); - - final edvardGried = 'EBG'.toCryptogram(const CryptogramScheme.french()); - expect(edvardGried, [Note.e, Note.b, Note.g]); - - final franzSchubert = - 'F. SCH'.toCryptogram(const CryptogramScheme.german()); - expect(franzSchubert, [Note.f, Note.e.flat, Note.c, Note.b]); - - final gustavHolst = - 'GSAH'.toCryptogram(const CryptogramScheme.german()); - expect(gustavHolst, [Note.g, Note.e.flat, Note.a, Note.b]); - - final jehanAlain = - 'ALAIN'.toCryptogram(const CryptogramScheme.frenchVariant()); - expect(jehanAlain, [Note.a, Note.d, Note.a, Note.a, Note.f]); - - final johannesBrahms = - 'BAHS'.toCryptogram(const CryptogramScheme.german()); - expect(johannesBrahms, [Note.b.flat, Note.a, Note.b, Note.e.flat]); - - final johannSebastianBach = - 'BACH'.toCryptogram(const CryptogramScheme.german()); - expect(johannSebastianBach, [Note.b.flat, Note.a, Note.c, Note.b]); - - final johnCage = 'CAGE'.toCryptogram(const CryptogramScheme.german()); - expect(johnCage, [Note.c, Note.a, Note.g, Note.e]); - - final josephHaydn = - 'HAYDN'.toCryptogram(const CryptogramScheme.german()); - expect(josephHaydn, [Note.b, Note.a, Note.d, Note.d, Note.g]); - - final metaAbegg = 'ABEGG'.toCryptogram(const CryptogramScheme.german()); - expect(metaAbegg, [Note.a, Note.b.flat, Note.e, Note.g, Note.g]); - - final nielsGade = 'GADE'.toCryptogram(const CryptogramScheme.german()); - expect(nielsGade, [Note.g, Note.a, Note.d, Note.e]); - - final paulSacher = - 'SACHER'.toCryptogram(const CryptogramScheme.german()); - expect( - paulSacher, - [Note.e.flat, Note.a, Note.c, Note.b, Note.e, Note.d], - ); - - final robertSchumann = - 'SCHA'.toCryptogram(const CryptogramScheme.german()); - expect(robertSchumann, [Note.e.flat, Note.c, Note.b, Note.a]); - - final asch1 = 'ASCH'.toCryptogram(const CryptogramScheme.german()); - expect(asch1, [Note.a.flat, Note.c, Note.b]); - - final asch2 = 'A SCH'.toCryptogram(const CryptogramScheme.german()); - expect(asch2, [Note.a, Note.e.flat, Note.c, Note.b]); - }); - }); - }); -} diff --git a/test/model/main.dart b/test/model/main.dart index 2378e01..7b22f33 100644 --- a/test/model/main.dart +++ b/test/model/main.dart @@ -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(); } diff --git a/test/model/name_test.dart b/test/model/name_test.dart index fa254ad..f3a1171 100644 --- a/test/model/name_test.dart +++ b/test/model/name_test.dart @@ -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() { @@ -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( @@ -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'); @@ -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); }, ); });