HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Transposing notes by one whole step

Submitted by: @import:stackexchange-codereview··
0
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 (.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:

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.