Skip to content

Commit

Permalink
Convert Sight Reading practice to TS
Browse files Browse the repository at this point in the history
  • Loading branch information
BHSPitMonkey committed Mar 2, 2024
1 parent a2ab3aa commit 73d9430
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 54 deletions.
2 changes: 1 addition & 1 deletion js/entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import injectTapEventPlugin from 'react-tap-event-plugin';
import Application from './application';
import Home from './home';
import About from './about';
import SightReadingPracticeIntro from './modes/sight-reading-practice-intro.jsx';
import SightReadingPracticeIntro from './modes/sight-reading-practice-intro';
import PerfectPitchPracticeIntro from './modes/perfect-pitch-practice-intro';
import FreePlayIntro from './modes/free-play-intro';

Expand Down
5 changes: 3 additions & 2 deletions js/modes/sight-reading-practice-intro.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
/**
* Intro screen for the Sight Reading practice mode
*
* Intended to show user-configurable settings for the practice session
* before starting, along with a button to begin.
*/
export default class SightReadingPracticeIntro {
render(): any;
export default class SightReadingPracticeIntro extends React.Component {
render(): React.JSX.Element;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import PracticeIntro from '../common/practice-intro';
import SightReadingPractice from './sight-reading-practice.jsx';
import SightReadingPractice from './sight-reading-practice';

/**
* Intro screen for the Sight Reading practice mode
Expand Down
84 changes: 43 additions & 41 deletions js/modes/sight-reading-practice.d.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import React from 'react';
import NoSleep from 'nosleep';
import { PreferencesState, PreferenceGroup } from '../common/practice-intro';
import Synth from '../synth';
type SightReadingPracticeProps = {
prefs: PreferencesState;
};
/**
* Component providing the sight reading practice game (in entirety)
*/
declare class SightReadingPractice {
constructor(props: any);
nosleep: any;
clefs: any[];
types: any[];
export default class SightReadingPractice extends React.Component {
static contextTypes: any;
static prefsDefinitions: PreferenceGroup[];
clefs: string[];
context: {
snackbar: (message: string, duration?: number) => void;
synth: Synth;
};
props: SightReadingPracticeProps;
nosleep: NoSleep;
notesOn: {
[x: number]: true;
};
state: {
clef: any;
keySignature: any;
keys: any[];
clef: 'bass' | 'alto' | 'treble' | 'grand';
flatKeyboardLabels: boolean;
keys: any;
keysDown?: any;
keySignature: any;
};
notesOn: {};
/**
* Generate a new question to ask and update state
*/
newQuestion(): void;
/**
* Handle a guessed answer and judge it to be right or wrong.
*
* Guesses could be sent here from multiple places:
* - The on-screen musical keyboard (KeyboardButtons component)
* - Keyboard input
*
* @param {Set} entries The names of the key(s) being guessed.
*/
handleGuess(entry: any): void;
types: string[];
constructor(props: SightReadingPracticeProps);
r(arr: any): any;
/**
* We need to disable nosleep on unmount in case the user leaves the practice session by some other means than by
* using the back button in the AppBar (e.g. by using their browser navigation)
Expand All @@ -37,7 +41,6 @@ declare class SightReadingPractice {
* Handler for after we've been granted the MIDI access we requested at launch
*/
onMidiAccessGranted(midi: any): void;
r(arr: any): any;
/**
* Handler for new MIDI devices connected after launch
*/
Expand All @@ -55,23 +58,22 @@ declare class SightReadingPractice {
keys: any[];
flatKeyboardLabels: boolean;
};
/**
* Generate a new question to ask and update state
*/
newQuestion(): void;
/**
* Handle a guessed answer and judge it to be right or wrong.
*
* Guesses could be sent here from multiple places:
* - The on-screen musical keyboard (KeyboardButtons component)
* - Keyboard input
*
* @param {Set} entries The names of the key(s) being guessed.
*/
handleGuess(entry: any): void;
correctGuess(): void;
incorrectGuess(): void;
render(): any;
}
declare namespace SightReadingPractice {
namespace contextTypes {
let snackbar: any;
let appbar: any;
}
let prefsDefinitions: {
header: string;
items: {
type: string;
label: string;
pref: string;
default: boolean;
}[];
}[];
render(): React.JSX.Element;
}
export default SightReadingPractice;
export {};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import SheetMusicView from '../sheet-music-view';
import KeyboardButtons from '../keyboard-buttons';
import * as Midi from '../midi';
import PD from 'probability-distributions';
import { PreferencesState, PreferenceGroup } from '../common/practice-intro';;
import PropTypes from 'prop-types';
import Synth from '../synth';

// Private constants
const possibleClefs = ['treble', 'bass', 'alto'];
Expand All @@ -36,11 +38,31 @@ const clefOptions = {
},
};

type SightReadingPracticeProps = {
prefs: PreferencesState,
};

/**
* Component providing the sight reading practice game (in entirety)
*/
export default class SightReadingPractice extends React.Component {
constructor(props) {
static contextTypes;
static prefsDefinitions: PreferenceGroup[];
clefs: string[];
context: { snackbar: (message: string, duration?: number) => void, synth: Synth };
props: SightReadingPracticeProps;
nosleep: NoSleep;
notesOn: { [x: number]: true };
state: {
clef: 'bass' | 'alto' | 'treble' | 'grand',
flatKeyboardLabels: boolean,
keys,
keysDown?,
keySignature,
};
types: string[];

constructor(props: SightReadingPracticeProps) {
super(props);

this.nosleep = new NoSleep();
Expand Down Expand Up @@ -207,13 +229,16 @@ export default class SightReadingPractice extends React.Component {
// Choose a number of sharps/flats, from 0 to 7, favoring lower amounts
var numAccidentals = Math.floor(PD.rbeta(1, 1, 3)[0] * 8);
var candidateSignatures = [];
// @ts-ignore keySignature.keySpecs actually exists
var keySignatures = Object.keys(Vex.Flow.keySignature.keySpecs);
keySignatures.forEach((key) => {
// @ts-ignore keySignature.keySpecs actually exists
if (Vex.Flow.keySignature.keySpecs[key]['num'] == numAccidentals) {
candidateSignatures.push(key);
}
});
keySignature = r(candidateSignatures);
// @ts-ignore keySignature.keySpecs actually exists
if (Vex.Flow.keySignature.keySpecs[keySignature].acc == "b") {
flatKeyboardLabels = true;
}
Expand All @@ -235,6 +260,7 @@ export default class SightReadingPractice extends React.Component {
let scale = Teoria.scale(tonic, scaleType);

// Branch based on type (single, chord, cluster)
let notes = [];
let type = r(this.types);
switch (type) {
case 'single':
Expand All @@ -256,7 +282,7 @@ export default class SightReadingPractice extends React.Component {
}
}
}
var notes = [Teoria.note(key + accidental + octave)];
notes = [Teoria.note(key + accidental + octave)];
break;
case 'chords':
// First pick a root Note from the chosen Scale...
Expand All @@ -265,7 +291,6 @@ export default class SightReadingPractice extends React.Component {
let root = scaleNotes[scaleDegree];

// If accidentals are enabled, choose a random chord quality
var notes;
if (this.props.prefs.accidentals) {
// Then pick a chord type...
let chordType = r(possibleChordTypes);
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@types/react": "^18.2.58",
"@types/vexflow": "^1.2.34",
"@types/vexflow": "^1.2.36",
"babel-loader": "^9.1.3",
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"isolatedModules": true,
// use typescript to transpile jsx to js
"jsx": "react",
"lib": ["DOM", "ESNext.Array"]
"downlevelIteration": true,
"lib": ["DOM", "ES2016", "ESNext.Array"]
},
"exclude": [
"./build/**/*" // This is what fixed it!
Expand Down

0 comments on commit 73d9430

Please sign in to comment.