diff --git a/src/helpers/playMusic.js b/src/helpers/playMusic.js index 64e8a7c..2d41187 100644 --- a/src/helpers/playMusic.js +++ b/src/helpers/playMusic.js @@ -17,9 +17,11 @@ function stopAll() { /** * Plays a sequence of notes in piano + * @params {string} selectedInstrument * @params {object} answer * @params {array} guess * @params {integer} currentRow + * @params {integer} volume * @return */ export function playSequence(selectedInstrument, answer, guess, currentRow, volume) { @@ -49,9 +51,9 @@ export function playSequence(selectedInstrument, answer, guess, currentRow, volu /** * Play celebration + * @params {string} selectedInstrument * @params {object} answer - * @params {array} guess - * @params {integer} currentRow + * @params {integer} volume * @return */ @@ -71,13 +73,16 @@ export function playCelebrationSequence(selectedInstrument, answer, volume) { /** * Plays a single note + * @params {string} selectedInstrument * @params {string} note * @params {object} answer * @params {integer} currentRow + * @params {integer} volume + * @params {integer} octave * @return */ -export function playNote(selectedInstrument, note, answer, currentNote, volume) { +export function playNote(selectedInstrument, note, answer, currentNote, volume, octave=answer.sequence[currentNote].slice(-1)) { //Stop any previous melodies from playing stopAll(); const instrument = instrumentsObj[selectedInstrument]; @@ -95,7 +100,8 @@ export function playNote(selectedInstrument, note, answer, currentNote, volume) } instrument.loaded().then(() => { - const octave = answer.sequence[currentNote].slice(-1); + //If octave is passed in as an optional param, get it from that; otherwise, get it from the octave. + //const oct = octave || answer.sequence[currentNote].slice(-1); const now = context.currentTime; instrument.start({ note: `${note}${octave}`, time: now, duration: 0.5 }); }) diff --git a/src/routes/Practice.jsx b/src/routes/Practice.jsx index f751b7e..2156cdd 100644 --- a/src/routes/Practice.jsx +++ b/src/routes/Practice.jsx @@ -4,7 +4,7 @@ import VolumeContext from '../contexts/VolumeContext' import PianoNew from '../PianoNew' import isNote from '../helpers/isNote' import getNote from '../helpers/getNote' -import { playNote } from "../helpers/playMusic"; +import { playNote, playSequence } from "../helpers/playMusic"; import Instruments from '../Instruments' import Grid from '@mui/material/Grid'; import styles from './Practice.module.css' @@ -12,21 +12,62 @@ import styles from './Practice.module.css' export default function Practice() { const [volume, setVolume] = useState(3); + const [inProgress, setInProgress] = useState(false); + const [isPaused, setIsPaused] = useState(false); const [gameOver, setGameOver] = useState(false); const [instrument, setInstrument] = useState('acoustic_grand_piano') const [octave, setOctave] = useState(4); const [error, setError] = useState(null); - const [hasFlats, setHasFlats] = useState(false); - const answer = { sequence: [`D${octave}`] } + const [guess, setGuess] = useState(""); + const [answer, setAnswer] = useState({ sequence: [`Ab${octave}`], duration: [1], hasFlats: false }) + const [firstTimePlayed, setFirstTimePlayed] = useState(true); + const possibleNotes = ["A", "B", "C", "D", "E", "F", "G", "Db", "C#", "Eb", "D#", "Gb", "F#", "Ab", "G#", "Bb", "A#"] + const possibleOctaves = [3, 4, 5]; + + function getRandomElement(possibleValues) { + const randomIndex = Math.floor(Math.random() * possibleValues.length) + return possibleValues[randomIndex]; + } + + function getNewNote() { + const selectedNote = getRandomElement(possibleNotes); + const hasFlats = selectedNote[1] === "b"; + setAnswer({ sequence: [`${selectedNote}${getRandomElement(possibleOctaves)}`], duration: [1], hasFlats: hasFlats }) + } + function startGame() { + getNewNote(); + setInProgress(true); + setIsPaused(false); + } + + function playGame() { + if (firstTimePlayed) { + setFirstTimePlayed(false); + } + setIsPaused(false); + playSequence(instrument, answer, undefined, undefined, volume); + } function handlePianoPress(note) { - console.log('note', note) handleKeyDown({ key: note }); } + function compareNoteWithAnswer(note, answerNote) { + //note: F. Ab C# G. + //answerNote: Gb3 F4 C#3 + console.log('!!!comparing', note, answerNote) + console.log('1) answerNote.slice(0,-1)', answerNote.slice(0,-1)) + console.log('2) with', note[1] === '.' ? note[0] : note) + return answerNote.slice(0,-1) === (note[1] === '.' ? note[0] : note) + } - function handleSubmit() { - console.log('submitting...') - } + // function getPercentage() { + // console.log("guess", guess) + // console.log("guess.length", guess.length) + // console.log("typeof guess", typeof guess) + // console.log("guess[0]", guess[0]) + // console.log("guess[1]", guess[1]) + // return `${guess.split("").filter((el) => el === "\uDFE9").length} / ${guess.length}`; + // } const handleKeyDown = useCallback( (event) => { @@ -37,25 +78,24 @@ export default function Practice() { case event.keyCode === 37: // The left arrow key was pressed. console.log("left key pressed", event.keyCode) - setOctave(octave > 3 ? octave-1 : octave); + setOctave(octave > 3 ? octave - 1 : octave); break; case event.keyCode === 39: // The right arrow key was pressed. - setOctave(octave < 5 ? octave+1 : octave); + setOctave(octave < 5 ? octave + 1 : octave); break; case isNote(event.key): /*Update guess state after valid note*/ let note = getNote(event, answer?.hasFlats); - console.log("note", note) if (note[1] === "b") { note = note[0].toUpperCase() + note[1]; } else { note = note.toUpperCase(); } - + /*Play the note in the same octave as the corresponding answer*/ - playNote(instrument, note, answer, 0, volume); + playNote(instrument, note, answer, 0, volume, octave); //setError(""); //highlight piano keyboard notes @@ -82,9 +122,19 @@ export default function Practice() { } } }, 200) - break; - case event.key === "Enter": - handleSubmit(event); + + if (inProgress && !isPaused) { + console.log('comparing...') + if (compareNoteWithAnswer(note, answer?.sequence[0] )) { + setGuess(guess + '🟩') + getNewNote(); + setFirstTimePlayed(true); + setIsPaused(true); + } else { + setGuess(guess + '🟥') + } + } + break; case RegExp("^[a-zA-Z0-9]$").test(event.key): setError(`${event.key.toUpperCase()} is not a valid note.`); @@ -93,42 +143,38 @@ export default function Practice() { break; } }, - [answer, gameOver, handleSubmit, volume, instrument] + [answer, gameOver, volume, instrument, guess, isPaused] ); useEffect(() => { //listen to keyboard events window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); - }, [handleSubmit, handleKeyDown]); + }, [handleKeyDown]); return ( <> - + +
{answer?.sequence[0]}{guess}
+ {/* {getPercentage()} */} +
+ - {/* - Key - - setKey(e.target.value)} - sx={{ fontSize: '1.6rem' }} - > - - - */} - + {inProgress || isPaused ? + <> + + + + + + : }
diff --git a/src/routes/Practice.module.css b/src/routes/Practice.module.css index e88d2c1..3abc68e 100644 --- a/src/routes/Practice.module.css +++ b/src/routes/Practice.module.css @@ -1,3 +1,7 @@ .keyboard { margin-top: 3em; +} +.guessContainer { + max-width: 70%; + border: 1px solid pink; } \ No newline at end of file