import { CHROMATIC, NATURAL, getNoteAt, getAnswerChoices } from './music.js'; import { FRET_COUNT } from './fretboard.js'; export function genMode1Question(numStrings, naturalOnly) { let stringIdx, fret, note; let attempts = 0; do { stringIdx = Math.floor(Math.random() * numStrings); fret = Math.floor(Math.random() * (FRET_COUNT + 1)); note = getNoteAt(stringIdx, fret, numStrings); attempts++; } while (naturalOnly && !NATURAL.includes(note) && attempts < 100); const choices = getAnswerChoices(note, naturalOnly); return { stringIdx, fret, note, choices }; } export function genMode2Question(numStrings, naturalOnly) { const pool = naturalOnly ? NATURAL : CHROMATIC; const targetNote = pool[Math.floor(Math.random() * pool.length)]; const rangeLen = Math.random() < 0.5 ? 4 : 5; const fretStart = Math.floor(Math.random() * (FRET_COUNT - rangeLen + 1)); const fretEnd = fretStart + rangeLen; const correctSet = new Set(); for (let s = 0; s < numStrings; s++) { for (let f = fretStart; f <= fretEnd; f++) { if (getNoteAt(s, f, numStrings) === targetNote) { correctSet.add(`${s},${f}`); } } } return { targetNote, fretStart, fretEnd, correctSet }; } export function evaluateMode2(selection, correctSet) { const allCorrect = [...correctSet].every(k => selection.has(k)) && [...selection].every(k => correctSet.has(k)); const missed = [...correctSet].filter(k => !selection.has(k)).length; const extra = [...selection].filter(k => !correctSet.has(k)).length; return { allCorrect, missed, extra }; }