Skip to content

Commit 5aa16d5

Browse files
author
Salma Alam-Naylor
committed
Proof of Concept for similar modes - not fully working yet
1 parent 4a176c3 commit 5aa16d5

14 files changed

+239
-7
lines changed

apps/fretonator-web/src/app/common/fret-map/fret-map.service.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,3 +1351,55 @@ describe('FretMapService:convertFretMapConfigurationToDisplayString', () => {
13511351
expect(result).toBe('A flat Minor Pentatonic');
13521352
});
13531353
});
1354+
1355+
describe('FretMapService:getSimilarModes', () => {
1356+
let service: FretMapService;
1357+
1358+
beforeEach(() => {
1359+
TestBed.configureTestingModule({});
1360+
service = TestBed.inject(FretMapService);
1361+
});
1362+
1363+
it('returns correctly for an input of c natural ionian', () => {
1364+
const result = service.getSimilarModes(cIonianMode, Mode.ionian);
1365+
1366+
expect(result).toBe([
1367+
{
1368+
noteDisplayName: 'D',
1369+
note: 'd',
1370+
mode: 'dorian',
1371+
noteExtender: 'natural'
1372+
},
1373+
{
1374+
noteDisplayName: 'E',
1375+
note: 'e',
1376+
mode: 'phrygian',
1377+
noteExtender: 'natural'
1378+
},
1379+
{
1380+
noteDisplayName: 'F',
1381+
note: 'f',
1382+
mode: 'lydian',
1383+
noteExtender: 'natural'
1384+
},
1385+
{
1386+
noteDisplayName: 'G',
1387+
note: 'g',
1388+
mode: 'mixolydian',
1389+
noteExtender: 'natural'
1390+
},
1391+
{
1392+
noteDisplayName: 'A',
1393+
note: 'a',
1394+
mode: 'aolian',
1395+
noteExtender: 'natural'
1396+
},
1397+
{
1398+
noteDisplayName: 'B',
1399+
note: 'b',
1400+
mode: 'locrian',
1401+
noteExtender: 'natural'
1402+
}
1403+
]);
1404+
});
1405+
});

apps/fretonator-web/src/app/common/fret-map/fret-map.service.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ import {
88
ModeMap,
99
NoteExtenderString,
1010
NoteObject,
11-
NoteSymbol
11+
NoteSymbol,
12+
SimilarMode,
13+
SimilarModes
1214
} from '../../util/types';
1315
import {
1416
ChordPatterns,
1517
ModePatterns,
1618
ModeSelectorObjects,
1719
NoteToStringAndFretMap,
1820
Octave,
19-
ScaleDegrees
21+
ScaleDegrees,
22+
SimilarModePatterns
2023
} from '../../util/constants';
2124
import { JamTracksData } from '../../data/jamTracks';
2225

@@ -257,7 +260,7 @@ export class FretMapService {
257260

258261
for (let i = 0; i < modePattern.length - 1; i++) {
259262
newNote = this.generateNextNote(currentNote, modePattern[i]);
260-
newNote.displayName = this.convertNoteObjectToHumanReadable(newNote)
263+
newNote.displayName = this.convertNoteObjectToHumanReadable(newNote);
261264

262265
newMode.push(newNote);
263266
currentNote = newNote;
@@ -408,6 +411,36 @@ export class FretMapService {
408411
note: this.convertNoteObjectToHumanReadable(noteObject),
409412
type: chordPattern[index]
410413
}));
414+
};
415+
416+
getNoteExtenderStringFromNoteObject = (noteObject: NoteObject): NoteExtenderString => {
417+
if (this.isSharp(noteObject, noteObject.name)) {
418+
return NoteExtenderString.sharp;
419+
}
420+
421+
if (this.isFlat(noteObject, noteObject.name)) {
422+
return NoteExtenderString.flat;
423+
}
424+
425+
if (this.isNatural(noteObject, noteObject.name)) {
426+
return NoteExtenderString.natural;
427+
}
428+
};
411429

430+
getSimilarModes = (modeMap: ModeMap, inputMode: Mode): SimilarModes => {
431+
const firstModeInPattern = SimilarModePatterns.indexOf(inputMode);
432+
433+
const similarModes = modeMap
434+
.map((noteObject, index) => {
435+
return {
436+
noteDisplayName: noteObject.displayName,
437+
note: noteObject.name,
438+
mode: SimilarModePatterns[firstModeInPattern + index],
439+
noteExtender: this.getNoteExtenderStringFromNoteObject(noteObject),
440+
} as unknown as SimilarMode;
441+
});
442+
443+
similarModes.shift();
444+
return similarModes;
412445
};
413446
}

apps/fretonator-web/src/app/common/fretonator/fretonator.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,9 @@ <h4 class="fretonator__playCta">
8585
<app-interval-map [intervalMap]="intervalMap"></app-interval-map>
8686

8787
<app-chord-map [chordMap]="chordMap"></app-chord-map>
88+
89+
<app-similar-modes [modeDisplayString]="modeDisplayString"
90+
[modeMap]="modeMap"
91+
[mode]="mode"></app-similar-modes>
92+
8893
</div>

apps/fretonator-web/src/app/common/fretonator/fretonator.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { IntervalMapModule } from './interval-map/interval-map.module';
77
import { ScaleMapModule } from './scale-map/scale-map.module';
88
import { IsTheoreticalScalePipe } from './is-theoretical-scale.pipe';
99
import { SpeakerModule } from '../svgs/speaker/speaker.module';
10+
import { SimilarModesModule } from './similar-modes/similar-modes.module';
1011

1112
@NgModule({
1213
declarations: [
@@ -19,7 +20,8 @@ import { SpeakerModule } from '../svgs/speaker/speaker.module';
1920
ChordMapModule,
2021
IntervalMapModule,
2122
ScaleMapModule,
22-
SpeakerModule
23+
SpeakerModule,
24+
SimilarModesModule
2325
],
2426
exports: [
2527
FretonatorComponent

apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,4 @@ export class GetEnharmonicRouterLinkPipe implements PipeTransform {
2424

2525
return ['/', newNote, newNoteExtender, mode];
2626
}
27-
2827
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<div class="similarModes">
2+
<h4 class="similarModes__title">Did you know?</h4>
3+
<p class="similarModes__copy">If you know the patterns of {{modeDisplayString}}, you'll know the modes below. Just shift your fingers along the
4+
fret board.</p>
5+
6+
<app-chips>
7+
<app-chip *ngFor="let mode of similarModes"
8+
[note]="mode.note"
9+
[noteExtender]="mode.noteExtender"
10+
[mode]="mode.mode"
11+
selectedColor="default">{{mode.displayName}} {{mode.mode | titlecase}}</app-chip>
12+
</app-chips>
13+
</div>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
@import "../../../../styles/vars";
2+
@import "../../../../styles/functions";
3+
@import "../../../../styles/mixins";
4+
@import "../../../../styles/typography";
5+
6+
.similarModes {
7+
background-color: var(--peach);
8+
padding: pxToRem($grid-unit * 4);
9+
margin-left: pxToRem($grid-unit * -4);
10+
margin-right: pxToRem($grid-unit * -4);
11+
margin-top: pxToRem($grid-unit * 4);
12+
display: flex;
13+
flex-direction: column;
14+
align-items: center;
15+
16+
@media screen and (min-width: $screen-med) {
17+
align-items: flex-start;
18+
}
19+
}
20+
21+
.similarModes__title {
22+
@include info_container_title();
23+
}
24+
25+
.similarModes__copy {
26+
@include font_bodyCopy();
27+
margin-bottom: pxToRem($grid-unit * 2);
28+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { SimilarModesComponent } from './similar-modes.component';
4+
5+
describe('SimilarModesComponent', () => {
6+
let component: SimilarModesComponent;
7+
let fixture: ComponentFixture<SimilarModesComponent>;
8+
9+
beforeEach(async(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [ SimilarModesComponent ]
12+
})
13+
.compileComponents();
14+
}));
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(SimilarModesComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import { Mode, ModeMap, SimilarModes } from '../../../util/types';
3+
import { FretMapService } from '../../fret-map/fret-map.service';
4+
import { ActivatedRoute } from '@angular/router';
5+
6+
@Component({
7+
selector: 'app-similar-modes',
8+
templateUrl: './similar-modes.component.html',
9+
styleUrls: ['./similar-modes.component.scss']
10+
})
11+
export class SimilarModesComponent implements OnInit {
12+
@Input() modeMap: ModeMap;
13+
@Input() mode: Mode;
14+
@Input() modeDisplayString: string;
15+
similarModes: SimilarModes = [];
16+
17+
constructor(private activatedRoute: ActivatedRoute,
18+
public fretMapService: FretMapService) {
19+
}
20+
21+
ngOnInit(): void {
22+
this.activatedRoute.params.subscribe(() => this.onRouteChange());
23+
this.getSimilarModes();
24+
}
25+
26+
onRouteChange() {
27+
this.getSimilarModes();
28+
}
29+
30+
getSimilarModes() {
31+
this.similarModes = this.fretMapService.getSimilarModes(this.modeMap, this.mode);
32+
}
33+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { SimilarModesComponent } from './similar-modes.component';
4+
import { ChipsModule } from '../../chips/chips.module';
5+
6+
7+
@NgModule({
8+
declarations: [SimilarModesComponent],
9+
exports: [
10+
SimilarModesComponent
11+
],
12+
imports: [
13+
CommonModule,
14+
ChipsModule
15+
]
16+
})
17+
export class SimilarModesModule { }

0 commit comments

Comments
 (0)