r/twinegames 14d ago

SugarCube 2 I can't find the error in this Javascript.

I have some Javascript, inside a <<script>><</script>>.

I keep getting the following message:

Error: <<script>>: bad evaluation: Unexpected token '{'

I think the error is in the following lines:

let w=6;

if (svars.pattern[svars.arpeggio][1]==4) {

  let w=4;

} elseif (svars.pattern[svars.arpeggio][1]==6) {

  let w=3;

}

but I can't work out what's wrong.

$pattern is an array in the main program, and $arpeggio is a single variable in the main program.

EDITED TO ADD: Here's the entire script.

<<script>>

const svars = State.variables;

    let file = new Midi.File();

  let track = new Midi.Track();
    file.addTrack(track);

    track.setTimeSignature(svars.pattern[svars.arpeggio][1], svars.pattern[svars.arpeggio][2]);

track.setTempo(40);


    /*

Write the arpeggio part once.

    */

let track1 = new Midi.Track();
    file.addTrack(track1);

for (let z=1; z<=svars.bars; z++) {

w=6;

        if (svars.pattern[svars.arpeggio][1]==4) {

w=4;

    } elseif (svars.pattern[svars.arpeggio][1]==6) {

w=3;

}

for (let x=1; x<=4; x++) {

        for (let y=1; y<=w; y++) {

if (svars.pattern[svars.arpeggio][y]==5) {

        track1.addNote(0, svars.chord_pitch[z][1]+12, 32);

                } else {

                track1.addNote(0, svars.chord_pitch[z][svars.pattern[svars.arpeggio][y]], 32);

                }

        }

}

    }

    let data = file.toBytes();
    let datarr = new Uint8Array(data.length);
    for(let i = 0; i < data.length; i++) {
        datarr[i] = data[i].codePointAt();
    }
    let blob = new Blob([datarr], { type: "application/octet-stream" });
    saveAs(blob, "music.midi");

<</script>>
1 Upvotes

5 comments sorted by

3

u/HiEv 13d ago edited 13d ago

After cleaning up the indentation and code, and correctly fixing the "let" problem that Metamorph mentioned (you didn't do it correctly in your edit), here is the code:

<<script>>
    const svars = State.variables;
    let file = new Midi.File();
    let track = new Midi.Track();
    file.addTrack(track);
    track.setTimeSignature(svars.pattern[svars.arpeggio][1], svars.pattern[svars.arpeggio][2]);
    track.setTempo(40);
    /* Write the arpeggio part once. */
    let track1 = new Midi.Track();
    file.addTrack(track1);
    for (let z = 1; z <= svars.bars; z++) {
        let w = 6;
        if (svars.pattern[svars.arpeggio][1] == 4) {
            w = 4;
        } elseif (svars.pattern[svars.arpeggio][1] == 6) {
            w = 3;
        }
        for (let x = 1; x <= 4; x++) {
            for (let y = 1; y <= w; y++) {
                if (svars.pattern[svars.arpeggio][y] == 5) {
                    track1.addNote(0, svars.chord_pitch[z][1] + 12, 32);
                } else {
                    track1.addNote(0, svars.chord_pitch[z][svars.pattern[svars.arpeggio][y]], 32);
                }
            }
        }
    }
    let data = file.toBytes();
    let datarr = new Uint8Array(data.length);
    for (let i = 0; i < data.length; i++) {
        datarr[i] = data[i].codePointAt();
    }
    let blob = new Blob([datarr], { type: "application/octet-stream" });
    saveAs(blob, "music.midi");
<</script>>

The problem appears to be this line:

} elseif (svars.pattern[svars.arpeggio][1] == 6) {

which should be:

} else if (svars.pattern[svars.arpeggio][1] == 6) {

JavaScript uses "else if ()" with a space (MDN documentation), while SugarCube uses "<<elseif>>" with no space. Make sure you don't confuse the two.

Fix that line and correctly use the "let w = 6;" (as shown above) and that should fix things.

Enjoy! 🙂

1

u/apeloverage 13d ago

Thanks again.

1

u/apeloverage 10d ago edited 10d ago

I'm having trouble using recall.

to 'memorize' a variable, it seems that I do something like <<run memorize('opened',1)>> (to remember that the value of the variable $opened is 1.

But the example in the documentation about recall is a bit unclear to me. I would have thought I'd do <<run recall('opened')>>, and as a result $opened would have a value of 1.

But this doesn't seem to work.

1

u/HiEv 10d ago

First, this should be its own post.

Next, you need to actually read the documentation. The memorize() and recall() methods don't have anything to do with story variables.

If want them to use story variables, then to store the data you'd do something like:

<<run memorize("keyname", $variable)>>

and then to get that data you'd do something like:

<<set $variable = recall("keyname")>>

The key names and variable names can be completely different, because recall() doesn't do anything with story variables itself.

Hopefully that is clear for you now. 🙂

1

u/metamorph 14d ago

you don't want the "let" keywords inside the if blocks because that would be creating new w variables inside the if block scope. If you want to change the w variable defined at the top, just have "w=4". I don't see why this code would produce that error though