MIDI_practice/html/assets/scripts/practice.js
2023-06-05 20:52:19 +02:00

178 lines
4.9 KiB
JavaScript

class Task {
/**
*
* @param {Array} keysig list of keysignatures to use (int 0-11) where 0 = C || a, 1 = G || e ...
* @param {boolean} natural enable/disable naturals
* @param {boolean} sharp enable/disable sharps
* @param {boolean} flat enable/disable flats
* @param {boolean} chord enable/disable chords (it's either chords or single notes)
* @param {boolean} extend enable/disable notes above C6 and below C2
*/
constructor() {
this.render = new Notation();
this.retrieve_settings();
this.solution = []; // keys to solve current problem
this.activeKeys = []; // currently pressed keys
this.active = true; // true while task can be solved
this.success = false;
this.generateTask();
}
generateTask() {
this.retrieve_settings();
this.success = false;
if (this.chord) {
this.generateChord();
} else {
this.generateNote();
}
}
generateNote() {
let pickFrom = [];
// TODO: choose signature
// TODO: maybe weight note likelyhood
if (this.natural) {
pickFrom.push(...nat_values);
if (this.extend) {
pickFrom.push(...nat_values_ex);
}
}
if (this.sharp) {
pickFrom.push(...shp_values);
if (this.extend) {
pickFrom.push(...shp_values_ex);
}
}
if (this.flat) {
pickFrom.push(...flt_values);
if (this.extend) {
pickFrom.push(...flt_values_ex);
}
}
// pick from generated pool
var randomResult = Math.floor(Math.random() * pickFrom.length);
let chosenNote = pickFrom[randomResult];
this.solution = [chosenNote[1]];
let clef = "";
// choose clef
if (chosenNote[1] == 40) {
Math.random() < 0.5 ? clef = "bass" : clef = "treble";
} else if (chosenNote[1] < 40) {
clef = "bass";
} else {
clef = "treble";
}
this.solution = [chosenNote[1]];
this.render.set_notes([new Noteset(clef, [chosenNote[0]])]);
}
generateChord() {
}
on_keyStateChange() {
if (this.active) {
this.checkActiveKeys();
} else {
console.log("Can't continue, still keys pressed.");
return;
}
if (this.success) {
this.generateTask();
} else if (this.activeKeys.length == 0) {
this.active = true;
}
}
/**
* Keeps Track of pressed keys
* @param {number} key
* @param {boolean} state
*/
changeKeyState(key, state) {
if (state) {
// start new timer
if (this.activeKeys.length == 0) {
this.active = true;
this.starttime = Date.now();
}
this.activeKeys.push(key);
} else {
let index = this.activeKeys.indexOf(key);
if (index != -1) {
this.activeKeys.splice(index, 1);
}
}
this.on_keyStateChange()
}
/**
* Checks if activeKeys fulfill current task
*/
checkActiveKeys() {
let failed = false;
this.activeKeys.forEach( key => {
if (!(this.solution.includes(key))) {
this.result_fail();
console.log("failed key: "+key);
failed = true;
}
});
if (failed) {
console.log("should have pressed: "+this.solution);
console.log("actually pressed: "+this.activeKeys);
return;
}
if (this.activeKeys.length == this.solution.length) {
if (Date.now() - this.starttime <= 500) {
console.log(this.solution);
console.log(this.activeKeys);
this.result_success();
return;
} else {
this.result_fail();
return;
}
}
}
result_fail() {
console.log("Wrong!");
this.active = false;
}
result_success() {
console.log("Correct!");
this.solution = [];
this.active = false;
this.success = true;
}
retrieve_settings() {
let cbx_naturals = document.getElementById("naturals");
let cbx_sharps = document.getElementById("sharps");
let cbx_flats = document.getElementById("flats");
let cbx_extended = document.getElementById("extended");
this.keysig = [0];
this.natural = cbx_naturals.checked;
this.sharp = cbx_sharps.checked;
this.flat = cbx_flats.checked;
this.chord = false;
this.extend = cbx_extended.checked;
}
}
// Starts the task loop
var task = new Task();