patternjavascriptMinor
Transposing notes by one whole step
Viewed 0 times
transposingwholenotesonestep
Problem
I am currently writing an app that converts musical keys. In a nutshell the conversion part of the script, is one giant if / then statement (if the user selected A then display B, etc etc.).
While this works perfectly fine, I definitely feel like this is fairly crude, and extremely lengthy, with all of the keys that need to be converted.
The following is an excerpt of the conversion function. It should be fairly readable, but basically the function first checks to make sure they've selected two keys (in this example C and B♭) and then checks the note (and whether or not it's sharp or flat), and then puts the correct answer in a couple of divs I have on the page (
```
//C to Bb Conversion
if (firstInstSelected == "C" && secondInstSelected == "Bb") {
if (firstNote == "A" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("B");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
if (firstNote == "A" && secondNote == "sharp" || firstNote == "B" && secondNote == "flat") {
$('#' + btnLabelSelected).find('.noteName').text("C");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
if (firstNote == "B" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("C");
$('#' + btnLabelSelected).find('.supNote').text("#");
return false;
}
if (firstNote == "C" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("D");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
While this works perfectly fine, I definitely feel like this is fairly crude, and extremely lengthy, with all of the keys that need to be converted.
The following is an excerpt of the conversion function. It should be fairly readable, but basically the function first checks to make sure they've selected two keys (in this example C and B♭) and then checks the note (and whether or not it's sharp or flat), and then puts the correct answer in a couple of divs I have on the page (
.noteName and .supNote).```
//C to Bb Conversion
if (firstInstSelected == "C" && secondInstSelected == "Bb") {
if (firstNote == "A" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("B");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
if (firstNote == "A" && secondNote == "sharp" || firstNote == "B" && secondNote == "flat") {
$('#' + btnLabelSelected).find('.noteName').text("C");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
if (firstNote == "B" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("C");
$('#' + btnLabelSelected).find('.supNote').text("#");
return false;
}
if (firstNote == "C" && secondNote == undefined) {
$('#' + btnLabelSelected).find('.noteName').text("D");
$('#' + btnLabelSelected).find('.supNote').text("");
return false;
}
Solution
yeah I'd use a data structure that encodes the "business logic" and then a simple lookup to update the UI:
This keeps your logic nice and tidy and easy to understand.
var notes = {
CBb: {
A: { noteName: "B", supNote: "" },
Asharp: { noteName: "C", supNote: "" },
Bflat: { noteName: "C", supNote: "" },
...
},
CF: {
A: { noteName: "B", supNote: "" },
Asharp: { noteName: "C", supNote: "" },
Bflat: { noteName: "C", supNote: "" },
...
}
};
var findNote = function (firstInstSelected, secondInstSelected, firstNote, secondNote) {
var outer = notes[firstInstSelected + (secondInstSelected || "")];
return outer && outer[firstNote + (secondNote || "")];
};
//...your event handler...
var note = findNote(firstInstSelected, secondInstSelected, firstNote, secondNote);
if (note) {
$("#" + btnLabelSelected).find(".noteName").text(note.noteName);
$("#" + btnLabelSelected).find(".supNote").text(note.supNote);
return false;
}
$('#' + btnLabelSelected).find('.noteName, .supNote').text("");
$('#' + btnLabelSelected).find('.noteFont').removeClass('hide');This keeps your logic nice and tidy and easy to understand.
Code Snippets
var notes = {
CBb: {
A: { noteName: "B", supNote: "" },
Asharp: { noteName: "C", supNote: "" },
Bflat: { noteName: "C", supNote: "" },
...
},
CF: {
A: { noteName: "B", supNote: "" },
Asharp: { noteName: "C", supNote: "" },
Bflat: { noteName: "C", supNote: "" },
...
}
};
var findNote = function (firstInstSelected, secondInstSelected, firstNote, secondNote) {
var outer = notes[firstInstSelected + (secondInstSelected || "")];
return outer && outer[firstNote + (secondNote || "")];
};
//...your event handler...
var note = findNote(firstInstSelected, secondInstSelected, firstNote, secondNote);
if (note) {
$("#" + btnLabelSelected).find(".noteName").text(note.noteName);
$("#" + btnLabelSelected).find(".supNote").text(note.supNote);
return false;
}
$('#' + btnLabelSelected).find('.noteName, .supNote').text("");
$('#' + btnLabelSelected).find('.noteFont').removeClass('hide');Context
StackExchange Code Review Q#32095, answer score: 6
Revisions (0)
No revisions yet.