Skip to content

コンピュータにルビーのコードを保存するの機能を実装しました #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 6, 2018

Conversation

t-kazu
Copy link
Collaborator

@t-kazu t-kazu commented Oct 28, 2018

#112 の内容です。
SB3Downloaderと同じように、zipファイルでダウンロードします。

rbファイルのダウンロードは、Google Chromeの場合警告がでるみたいですね。(参考までに)
screenshot from 2018-10-29 11-39-10

ダウンロードしたファイルの中身の例

require "smalruby"
Sprite.new("スプライト1",
           costumes: [
             {
               asset_id: "01ae57fd339529445cb890978ef8a054",
               name: "コスチューム1",
               bitmap_resolution: 1,
               md5: "01ae57fd339529445cb890978ef8a054.svg",
               data_format: "svg",
               rotation_center_x: 47,
               rotation_center_y: 55
             }
           ]) do
  move(10)
end

@takaokouji
Copy link

1つ1つはマージしなくて、全部ができたらマージしようとおもいます。
次のタスクができたら、このブランチにpushして、このPRを成長させてくださいね。

const downloadLink = document.createElement('a');
document.body.appendChild(downloadLink);

this.saveRuby().then(content => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zipではなく、テキストでcontentを取得する方法がわからなかったです。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zipの場合は処理時間がかかるため、非同期で処理しています。generateAsycなのが、それです。
今回はその必要はないため、thenメソッドの呼び出しは必要ありません。

let content = this.saveRuby();
のあと、
下記の行をそのまま処理すればいいと思うよ

Copy link
Collaborator Author

@t-kazu t-kazu Oct 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let content  = `require "smalruby"\n${this.props.rubyCode}`;

とした場合、

const url = window.URL.createObjectURL(content);

でエラーがでます

糸口が見えそうなので、これに関しては私の方でやってみます

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t-kazu
https://qiita.com/ledsun/items/93b0965c9720e0baf81c
の内容を参考にして、テキストファイルをどうにかして、Blobにしないといけないようですね。
詳しくは見れてないけど、なんとかなるといいな。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// saveRubyの戻り値をBlobにする。
const code = `require "smalruby"\n${this.props.rubyCode}`;
return new Blob([JSON.Stringfy(code, null, 2)], {
  type: "text/plain"
});

上記の Blob の戻り値を content とすればいいような気がします。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeを確認しました。
text/x-ruby-script
でした。

なので、以下が正しいですね。

// saveRubyの戻り値をBlobにする。
const code = `require "smalruby"\n${this.props.rubyCode}`;
return new Blob([JSON.Stringfy(code, null, 2)], {
  type: "text/x-ruby-script"
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mime-typeのチェックは、以下のHTMLで行いました。
https://qiita.com/Toshino3/items/4fec70fae9e85f693563
mime-checker.htmlとしてローカルファイルに保存して、chromeで表示しました。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <meta charset="utf-8" />
    </head>
    <body>
        ファイル選択
        <input type="file" id="targetBinFile">
        <input type="button" id="selectBinFileButton" value="読込">
        <br />
        <span id="fileTypeView"></span>
        <span> </span>
        <span id="mimeTypeView"></span>

        <script>
         // 実際のヘッダを見てMIMEタイプをチェックする。
         function getMimeType(header) {
             'use strict';

             var retv = '';
             switch (true) {
                 case header.startsWith('89504e47'):
                     retv = 'image/png';
                     break;
                 case header.startsWith('424d'):
                     retv = 'image/bmp';
                     break;
                 case header.startsWith('47494638'):
                     retv = 'image/gif';
                     break;
                 case header.startsWith('ffd8ff'):
                     retv = 'image/jpeg';
                     break;
                 case header.startsWith('25504446'):
                     // こんな風に画像以外にも応用可能ですよ。
                     retv = 'application/pdf';
                     break;
                 case header.startsWith('0'.repeat(128) + '4449434d'):
                     // DICOMは先頭128byteのNULL文字のあと、DICMが来る。
                     // …まあ、DICOMヘッダが無い
                     // いわゆる規約違反のDICOMファイルもたまにあるんですけどね…
                     retv = 'application/dicom';
                     break;
                 default:
                     retv = 'unknown';
                     break;
                     // 他にもシグネチャに応じた対応は可能かと思いますので、
                     // Wikipediaなど参考にされるのもよいのではないでしょか。
             }
             return retv;
         }

         (function () {
             'use strict';

             document.getElementById('selectBinFileButton').onclick = function () {

                 var file = document.getElementById('targetBinFile').files[0];

                 var fileReader = new FileReader();
                 fileReader.onloadend = function (e) {

                     // 先頭150byteも取得すれば
                     // 大方のシグネチャはカバーできるはず。
                     // そう、医用画像のDICOMファイルもね。
                     var arr = (new Uint8Array(e.target.result)).subarray(0, 150);

                     var header = '';
                     for (var i = 0; i < arr.length; i++) {
                         header += arr[i].toString(16);
                     }

                     // 拡張子で判断してるっぽい。
                     document.getElementById('fileTypeView').innerHTML = 'file.type: ' + (file.type === '' ? '(空)' : file.type);
                     // 自前で判定したMIMEタイプを表示してます。
                     document.getElementById('mimeTypeView').innerHTML = 'getMimeType: ' + getMimeType(header);
                 };
                 fileReader.readAsArrayBuffer(file);
             }
         }());
        </script>
    </body>
</html>

@nacl-takaokouji
Copy link

ひとまずzipね。了解です。先に進めてください。マージすべきではありませんので、タイトルにWIPをつけます。

@nacl-takaokouji
Copy link

と、僕のほうでは修正できないや。
このPRのタイトルに [WIP] をつけてください。

[WIP] コンピュータにルビーのコードを保存するの機能を実装しました

@t-kazu t-kazu changed the title コンピュータにルビーのコードを保存するの機能を実装しました [WIP] コンピュータにルビーのコードを保存するの機能を実装しました Oct 28, 2018
const downloadLink = document.createElement('a');
document.body.appendChild(downloadLink);

this.saveRuby().then(content => {
Copy link
Collaborator Author

@t-kazu t-kazu Oct 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let content  = `require "smalruby"\n${this.props.rubyCode}`;

とした場合、

const url = window.URL.createObjectURL(content);

でエラーがでます

糸口が見えそうなので、これに関しては私の方でやってみます

@t-kazu t-kazu changed the title [WIP] コンピュータにルビーのコードを保存するの機能を実装しました コンピュータにルビーのコードを保存するの機能を実装しました Oct 29, 2018
@takaokouji
Copy link

rbファイルのダウンロードは、Google Chromeの場合警告がでるみたいですね。(参考までに)

これはそのままでいいよ。

]);
}
saveRuby () {
const projectRuby = `require "smalruby"\n${this.props.rubyCode}`;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#115 (comment)
を参考にして、"をエンコードするように、修正してくださいませ。

@t-kazu t-kazu force-pushed the feature/download-ruby-code branch from cff049a to 2eea0c4 Compare October 29, 2018 02:51

const mapStateToProps = state => ({
projectFilename: getProjectFilename(state.scratchGui.projectTitle, projectTitleInitialState),
rubyCode: state.scratchGui.rubyCode.code

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このままだと、rubyCodeが更新されていないと古いままのスクリプトが出力されてしまいますね。
ここでは、rubyCodeを使わずに、RubyDownloader の内部で vm の targets の blocks を使って、rubyCode を出力しないといけないだろうな。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workspaceからしか変換したことがないので、少し時間が掛かってしまうかもしれません。

はい、理解しています。じっくりいきましょう。これが武本さんの最後のタスクになると思います。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最終的にはこの方法はよくないのですが、とりいそぎにやり方です。

プログラムで、ステージ、スプライトの先頭から末尾、というように順番に選択して、選択するたびに、 workspaceToCode を呼び出します。
そうすると、ステージとすべてのスプライトの rubyCode が得られます。

RubyDownloader の内部で vm の targets の blocks を使って、rubyCode を出力しないといけないのですが、 blocks から直接 ruby のコードを生成できるようにするのは次の段階とします。 scratch-vm のコードを読む限り、 scratch-blocks の block からコードを生成することよりも簡単そうなんだけど、Generatorが使えないけど、僕の方でなんとかする。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ステージやスプライトを変更すると、少なくともundoがリセットされるという不都合があるため、最終的には、この方法は採用しません。

@t-kazu t-kazu changed the title コンピュータにルビーのコードを保存するの機能を実装しました [WIP]コンピュータにルビーのコードを保存するの機能を実装しました Oct 29, 2018
@t-kazu
Copy link
Collaborator Author

t-kazu commented Oct 29, 2018

すみません。間違えて、git push -f してしまったので、

// saveRubyの戻り値をBlobにする。
const code = require "smalruby"\n${this.props.rubyCode};
return new Blob([JSON.Stringfy(code, null, 2)], {
type: "text/x-ruby-script"
});

というコメントが消えてしまいました。

@t-kazu
Copy link
Collaborator Author

t-kazu commented Oct 29, 2018

// saveRubyの戻り値をBlobにする。
const code = require "smalruby"\n${this.props.rubyCode};
return new Blob([JSON.Stringfy(code, null, 2)], {
type: "text/x-ruby-script"
});
の実行後は、

"require \"smalruby3\"\n\nSprite.new(\"スプライト1\",\n           costumes: [\n             {\n               asset_id: \"01ae57fd339529445cb890978ef8a054\",\n               name: \"コスチューム1\",\n               bitmap_resolution: 1,\n               md5: \"01ae57fd339529445cb890978ef8a054.svg\",\n               data_format: \"svg\",\n               rotation_center_x: 47,\n               rotation_center_y: 55\n             }\n           ]) do\n  move(10)\nend"

のように特殊文字がそのまま表示されるようです。

個人的には、以下のようにすれば良いと思っています。

const code = `require "smalruby"\n${this.props.rubyCode}`;
return new Blob([code], {
   type: "text/x-ruby-script"
 });

@takaokouji
Copy link

特殊文字がそのまま表示されるようです。

なるほど。手元では動作確認していませんでしたので、 JSON.Stringfy が期待と異なるようですので、使わなくてもいいです。

@t-kazu t-kazu changed the title [WIP]コンピュータにルビーのコードを保存するの機能を実装しました コンピュータにルビーのコードを保存するの機能を実装しました Nov 6, 2018
@t-kazu t-kazu changed the title コンピュータにルビーのコードを保存するの機能を実装しました [WIP]コンピュータにルビーのコードを保存するの機能を実装しました Nov 6, 2018
@t-kazu t-kazu changed the title [WIP]コンピュータにルビーのコードを保存するの機能を実装しました コンピュータにルビーのコードを保存するの機能を実装しました Nov 6, 2018
@takaokouji takaokouji merged commit 0c72c15 into smalruby:develop Nov 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants