Code viewer for World: Chat with GPT model (clone...
document.write(`
  <style>
    body {
      text-align: center;
      margin: 20px;
      padding: 20px;
      display: flex;
      flex-direction: column;
    }

    .sequencer {
      border-radius: 5px;
      width: fit-content;
      display: grid;
      grid-template-rows: repeat(6, 1fr);
      grid-template-columns: fit-content;
      margin: auto;
    }

    .note {
      border-radius: 5px;
      height: 4em;
      width: 4em;
      border-style: solid;
      border-width: 1px;
      border-color: lightgray;
      margin: 2px;
      outline: none;
    }

    .sequencer-row {
      display: inline-block;
      white-space: nowrap;
    }

    .note-is-active {
      background-color: green;
      border: 1px solid black;
    }

    .note-not-active {
      background-color: solid grey;
    }

    .toggle-play {
      display: flex;
    }

    .play-button {
      margin: auto;
    }
  </style>

<div id="sequencer" class="container sequencer">
  </div>
  <div class="toggle-play">
    <button id="play-button" class="play-button">Play</button>
  </div>

`);

// Load Tone.js and then execute the rest of the code
$.getScript("https://cdn.skypack.dev/tone", function () {
  window.onload = function () {
    const synths = makeSynths(6);
    const notes = ["F4", "Eb4", "C4", "Bb3", "Ab3", "F3"];
    let grid = makeGrid(notes);
    let beat = 0;
    let playing = false;
    let started = false;

    const configLoop = () => {
      const repeat = (time) => {
        grid.forEach((row, index) => {
          let synth = synths[index];
          let note = row[beat];
          if (note.isActive) {
            synth.triggerAttackRelease(note.note, "8n", time);
          }
        });

        beat = (beat + 1) % 8;
      };

      Tone.Transport.bpm.value = 120;
      Tone.Transport.scheduleRepeat(repeat, "8n");
    };

    const makeSequencer = () => {
      const sequencer = document.getElementById("sequencer");
      grid.forEach((row, rowIndex) => {
        const seqRow = document.createElement("div");
        seqRow.id = `rowIndex`;
        seqRow.className = "sequencer-row";

        row.forEach((note, noteIndex) => {
          const button = document.createElement("button");
          button.className = "note";
          button.addEventListener("click", function (e) {
            handleNoteClick(rowIndex, noteIndex, e);
          });

          seqRow.appendChild(button);
        });

        sequencer.appendChild(seqRow);
      });
    };

    const handleNoteClick = (clickedRowIndex, clickedNoteIndex, e) => {
      grid.forEach((row, rowIndex) => {
        row.forEach((note, noteIndex) => {
          if (clickedRowIndex === rowIndex && clickedNoteIndex === noteIndex) {
            note.isActive = !note.isActive;
            e.target.className = classNames(
              "note",
              { "note-is-active": !!note.isActive },
              { "note-not-active": !note.isActive }
            );
          }
        });
      });
    };

    const configPlayButton = () => {
      const button = document.getElementById("play-button");
      button.addEventListener("click", (e) => {
        if (!started) {
          Tone.start();
          Tone.getDestination().volume.rampTo(-10, 0.001);
          configLoop();
          started = true;
        }

        if (playing) {
          e.target.innerText = "Play";
          Tone.Transport.stop();
          playing = false;
        } else {
          e.target.innerText = "Stop";
          Tone.Transport.start();
          playing = true;
        }
      });
    };

    window.addEventListener("DOMContentLoaded", () => {
      configPlayButton();
      makeSequencer();
    });
  };
});