楽譜でプログラミングできる言語velatoのオンライン実行環境を作ったけどvelato-jsの挙動がなんかへん？ #atgt2020

# はじめに

ことしもあんたがたの季節がやってきました。

ちなみに「あんたがた」シリーズ第3弾です

1. [#atgt2019 14匁にC++の力で挑んだが甜菜はそんなものをふっとばして答えにたどり着く](https://qiita.com/yumetodo/items/4533d474e1f2ca7a00e7)
2. [#atgm_2020 12匁 特殊な数独をソルバーで解くためにpythonとpulpを勉強する](https://qiita.com/yumetodo/items/c05df2f01cdda8289bea)

# atgtとは

「Twitterのあんたがたに挑戦します」とは？
「あめちゃん」が考案し、2ちゃんねるVIP板にて開催された「[VIPPERのあんたがたに挑戦します](http://vipper.gozaru.jp/)」
GMが提示したパスワードから出題される謎を解き、その答えが指し示す「場所」に突撃すると、そこには次のパスワードが。

全国に散らばった謎を辿り、顔も知らない仲間達と協力する、世界で最もｗｋｔｋな遊びです。
そして、その遊びはTwitterの世界にも持ち込まれました。それが「Twitterのあんたがたに挑戦します」です。

新型コロナウイルスの流行により、依然として外出の自粛が要請されるなど大変な事態となっています。しかし、外出を不要とするシステムを使用し、今だからこそできるあんたがたをお届けします。

Twitterのあんたがたに挑戦します2020GMからのお知らせ

- ハッシュタグは [#atgt2020](https://twitter.com/hashtag/atgt2020?src=hashtag_click&f=live) を使用して下さい。
- 本イベントに関するツイートには全てこのハッシュタグを付けて下さい。
- GM側からあんたがたに対するサポートは以下の通りです。
問題が長時間解けない時のヒント出しを行います。
ヒントを出す前に、それが必要かどうかの投票を行います。
- GMは24時間体制でのサポートは行いません。
- サポートできない時間帯もございます。ご了承ください。

# 11匁

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【11匁まとめ】<br>今度は現れたのは一見ただの詩である。一部に線が引かれているようだが。<br>よく見てみると、これらの詩はそれぞれの行で歌謡曲の詞になっているようだった。それぞれ曲を調べてみると、「夜に駆ける」「地上の星」などの月や夜空を連想させるが曲が多いことがわかった<a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a></p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953558434017285?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>さらに見ると、歌詞の一部が太字になっていることがわかる。そこで、音感班によって太字部分のメロディの聴き取りが行われた。が、だからなんだというのだろう。</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953559621013504?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>出てくるメロディもよくわからない。そこで、問題に書いてある謎の丸や出てくためロディのアナグラムミュージックみから小林賢太郎のアナグラムネタにも話が飛んだがあまりしっくりこない。ここでヒントが投下される。</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953560808013824?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>幸せのショー【タイ】ム さぁ始めよう、みんなで!<br>歳【とる】度　増えた玩具もいつかは飽きては<br>ねえ 【サーチ】ライト照らして<br><br>どうやらタイトルサーチが必要らしい。ちなみにこれもちゃんと歌の歌詞だったりする。</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953561957277696?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>が、ここで停滞する。タイトルのアナグラムとかいろいろ調べて見るもわからない。そのままヒント二つ目が投下される。<br>超代品と。なんと、太字のメロディはヴエールのフランス語の「velato」を使えば良いらしい。何それ</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953563144220672?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>


そうして始まった11問目、歌詞から音程と曲を行ごとに(?)特定してなんかいろいろしたところ、velatoというプログラミング言語にたどり着きました。

- [Velato](http://velato.net/)
- [Velato | Note Tool](http://velato.net/Language/NoteTool/)

調を基準として音の度数が大事な言語のようです。
調？度数？という人は音楽教育業界で知らない人はいないヤマハのオンライン資料を見てください。ちなみに筆者は子どもの頃にヤマハ音楽教室に通っていて、この辺のこともやったような気はするのですが、あんまり覚えてません。カデンツとかその応用とかその検定試験とかやった気がするんだけどなぁ・・・。
[ヤマハ | 第4日 音階と調](https://jp.yamaha.com/services/music_pal/study/score/scale/index.html)

# ブラウザ上で動くplaygroundがない？なら作ればいいじゃない

velatoをオンライン上で動かせるのないのかなと思ってたのですが、どうもなさそうという。Twitterが舞台となって進むイベントの性質上、ブラウザ上で動かせるplaygroundがあるといいよなぁと思っていたところ、
[velato-js](https://github.com/eerwitt/velato-js)
という処理系を発見。じゃあこれを動かそう

## escodegenに依存している、それが問題だ。

velato-js自体はASTを作るところまでで、実際にブラウザで動かすためにJavaScriptに変換するのは[escodegen](https://github.com/estools/escodegen)というツールになる。

velato-jsのドキュメントにはbowerでとか書いてあるが、そんな4億年くらい昔に死んだツールは使いたくない。

幸いこれはnpmに公開されている。ということは[UNPKG](https://unpkg.com/)あたりからpre buildされたjsが手に入るんじゃね？そう思っていた。

ところが
[https://unpkg.com/browse/escodegen@2.0.0/](https://unpkg.com/browse/escodegen@2.0.0/)
にあるJSファイルはすべてブラウザでは動かない。`require`とかが見える。

READMEには

> Escodegen can be used in a web browser:
>
>```html
><script src="escodegen.browser.js"></script>
>```
>
> escodegen.browser.js can be found in tagged revisions on GitHub.

とある。tagged revisions on GitHubってどこやねん。Github packagesにもGithub Releaseにもtagついたcommitにもねーぞ。

仕方ないので手元でビルドする。

今どき珍しく`package-lock.json`すらないので`npm i`する。大量のwarningがでた。

よほどPR投げつけようかと思ったが、commitがあるのにPRのmergeがぜんぜんされてないというよくわかんない状態に陥ってるようだったので、断念した。

~~というかまじでせめてchange logくらい書いてください、何も言わずにさらっとメジャーバージョン上げんな、頼むし、まじで~~

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a> まじでescodegenにぶちきれてる。あとでどでかいPR投げつけてやるから覚悟しときぃや！ <a href="https://t.co/bN7XBXMFfM">pic.twitter.com/bN7XBXMFfM</a></p>&mdash; yumetodo (@yumetodo) <a href="https://twitter.com/yumetodo/status/1343129052433973250?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

`npm build`して成果物を`cp`してgit管理に含めるというなんともあまり良くない依存管理でとりあえず乗り切ることにしました。

## 仮完成

UIは雑にbootstrap4で組みました。リアルタイム謎解きですからね、動けばいいのですがさすがにcssなしは・・・と思ったので。そういえばbootstrap5が出たらしいですね。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a> よし、今からデプロイする <a href="https://t.co/v0mD7hXCgd">pic.twitter.com/v0mD7hXCgd</a></p>&mdash; yumetodo (@yumetodo) <a href="https://twitter.com/yumetodo/status/1343134907657162752?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

## エラーメッセージ表示機能追加

さすがにエラーはF12してみて！だとスマホユーザーが困ってしまうので、追加しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a> ここで皆様に簡易的なエラー表示機能追加のお知らせです <a href="https://t.co/7jGpiBBI6L">pic.twitter.com/7jGpiBBI6L</a></p>&mdash; yumetodo (@yumetodo) <a href="https://twitter.com/yumetodo/status/1343151079500861441?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

## どうも様子がおかしい

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【訂正】現在の問題について、公式ドキュメントと作問時に使用した公式コンパイラ、公式のコード生成器の仕様の間に矛盾がありました。数字の解釈について、画像の仕様を正として解答してください。大変申し訳ありません。引き続きあんたがたをお楽しみください。 <a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a> <a href="https://t.co/7g3ecRDv1g">pic.twitter.com/7g3ecRDv1g</a></p>&mdash; ツイッターのあんたがたに挑戦します2020公式 (@atgt2020) <a href="https://twitter.com/atgt2020/status/1343149086430490625?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">これって<a href="https://t.co/UCAC0Up9r5">https://t.co/UCAC0Up9r5</a><br>がバグってるのか、作問者の処理系がバグってるのかどっちです？<a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a> <a href="https://twitter.com/atgt2020?ref_src=twsrc%5Etfw">@atgt2020</a> <a href="https://t.co/eQqzts3rVB">https://t.co/eQqzts3rVB</a></p>&mdash; yumetodo (@yumetodo) <a href="https://twitter.com/yumetodo/status/1343149624345837569?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://t.co/fDrkizbduD">https://t.co/fDrkizbduD</a> の仕様は確かに公式ドキュメントに則っているものです(対応表の誤の列)。但し今回の作問に関してはこのツールを用いておらず、<a href="https://t.co/UcdRBnVKgo">https://t.co/UcdRBnVKgo</a> が出力する仕様に則ったVelato作者のコンパイラ(<a href="https://t.co/w6HqLNYsDl">https://t.co/w6HqLNYsDl</a>)を用いたためずれが生じました。 <a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a></p>&mdash; ツイッターのあんたがたに挑戦します2020公式 (@atgt2020) <a href="https://twitter.com/atgt2020/status/1343151360192126976?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">そのため、どちらかがバグというわけではないと考えられますが、今回は対応表正の列の仕様で作問したというのが経緯となります。以上よろしくお願いいたします。 <a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a></p>&mdash; ツイッターのあんたがたに挑戦します2020公式 (@atgt2020) <a href="https://twitter.com/atgt2020/status/1343151815005618176?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

どうも言語仕様に対して解釈違いがあるらしい・・・？(よくわかってない

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/stgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#stgt2020</a> 目視デバッグの結果が正しければ、velato.jsの143行目をいじればいけるかもしれません。具体的には、&quot;Minor Second&quot;の前に&quot;Perfect Prime&quot;を入れて、&quot;Major Seventh&quot;を取り除くというものです。</p>&mdash; flat/京山和将@昼夢堂:ゲムマ大阪予定 (@flat_ff) <a href="https://twitter.com/flat_ff/status/1343181598548746240?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote>

当該部分は次のようになっています。

```js:velato.js
    Note.prototype.asInt = function(rootNote) {
      var distance, int, intervalTable;
      distance = this.semitoneDistance(rootNote);

      /*
       * In the Root of C
       * c#  d  d# e f f# g g# a a# b
       * 0   1  2  3 4 5  - 6  7 8  9
       */
      intervalTable = ["Minor Second", "Major Second", "Minor Third", "Major Third", "Perfect Fourth", "Augmented Fourth, Diminished Fifth", "Minor Sixth", "Major Sixth", "Minor Seventh", "Major Seventh"];
      int = intervalTable.indexOf(distance.interval);
      if (int === -1) {
        return null;
      }
      return int;
    };
```

`intervalTable`を書き換えて、ということらしいのですが、ライブラリそのものに手を出したくないので、prototype経由で差し替えます。

```js
    const originalAsintFunc = Velato.Note.prototype.asInt;
    const replacedAsIntFunc = function(rootNote, changed) {
        var distance, int, intervalTable;
        distance = this.semitoneDistance(rootNote);
        /*
         * In the Root of C
         * c#  d  d# e f f# g g# a a# b
         * 1   2  3  4 5 6  - 7  8 9  10
         */
        intervalTable =  ["Perfect Prime", "Minor Second", "Major Second", "Minor Third", "Major Third", "Perfect Fourth", "Augmented Fourth, Diminished Fifth", "Minor Sixth", "Major Sixth", "Minor Seventh"];
        int = intervalTable.indexOf(distance.interval);
        if (int === -1) {
            return null;
        }
        return int;
    };
    //中略
    for (const form of document.forms) {
        //中略
        form.addEventListener("submit", e => {
            //中略
            Velato.Note.prototype.asInt = (form.changeRoot.checked) ? replacedAsIntFunc : originalAsintFunc;
            try {
                const re = Velato.compileJS(form.in.value);
                //中略
            } catch (e) {
                //中略
            }
		});
	}

```

そんなわけで次のような感じになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/eacb5bab-0689-ad81-21a0-4335ecf6cb58.png)

## token is null(未解決)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/537db921-074f-436b-8d68-b86efcdad125.png)

何故かエラー落ちするという現象が確認されています。

## 出力がおかしい(未解決)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/f635b550-0f5f-7da8-d2f0-a5ac2f802433.png)

実行結果は`f`となっていますが、脳内コンパイルされた方いわく、`fi`となるのが正しいようです。実際これを使って問題の次のステップに進めたのですから`fi`が正でしょう。ドウシテ・・・。

# 11匁のその後

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>調べてみると、音階を主言語とするプログラミング言語が存在するらしい。出てきたメロディをそこに突っ込めば解読できるっぽい。<br>コーディング班がウェブコンパイラを作って早速突っ込むもうまくいかない。音取りが間違っているのか？</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953564515885058?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【続き】<br>と思ったら、なんと作問課程で使用した生成器が公式ドキュメントと一部齟齬があったらしい。作者が同じなのに(何で？)<br>正直何がどう違うのかもよくわからないあんたがた。コンパイラの書き換えは難易度が高いと判断し、ついに人力コンパイルが決行される</p>&mdash; Naka/ジオン@はじめてのうぇぶなぞ (@Naka_musicgamE) <a href="https://twitter.com/Naka_musicgamE/status/1343953565904064512?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote>

人力コンパイル班の活躍で問題は次のステップに進めたようでよかったです。その後は埋め込んだツイートにぶら下がっているまとめをみるか、自分でTwitterを検索して見てください。

イベント終了時のGMのコメントがこちらです。きっとQiitaかなにかで記事を出してくれるでしょう。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">お疲れ様でした。音楽匁ではVelatoの仕様周りで(開発者側の矛盾とはいえ)確認不足で混乱させてすみませんでした。 (紗那) <a href="https://twitter.com/hashtag/atgt2020?src=hash&amp;ref_src=twsrc%5Etfw">#atgt2020</a></p>&mdash; ツイッターのあんたがたに挑戦します2020公式 (@atgt2020) <a href="https://twitter.com/atgt2020/status/1344604915507683329?ref_src=twsrc%5Etfw">December 31, 2020</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">想定解法ではなかったのですがvelato-jsの存在自体は作問時点で認知しており、人力ではなく何かしらのコンパイラで突破されることもあるだろうということで甜菜認定させていただきました(1月中には何かしらqiitaに記事あっぷします)</p>&mdash; 紗那 (@rare_shana3) <a href="https://twitter.com/rare_shana3/status/1344639783411228675?ref_src=twsrc%5Etfw">December 31, 2020</a></blockquote>

# 問題解説

[ヴェールに包まれた – atgt2020解説ページ](https://atgt2020.wordpress.com/2020/12/25/11/)

> Velatoで数字を記述するには、基準音(ドキュメントではCommand Root Note)を予め指定した上で、その基準音からどれだけ離れているかによって数字を指定する。離れれば離れるほど大きな数値を表すことになるのだが、実は公式ドキュメントの中でも「どれくらい離れるとどの数値に対応するのか」について矛盾が存在していた。

なるほどなぁ。この点については上のprototype injectionで対応できてたと思うんですよね。

それとは別のバグも踏んでしまった感があるのでつらい。

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>