2019年8月14日水曜日

子供用プログラミング教材まとめ

子供用プログラミング教材が増えてきたので、思考整理も兼ねて、まとめました。 内容は日々更新しており、今のところ最終更新は 2021-09-03 です。

なぜ子供用プログラミングを学ぶのか?

まず第一になぜ「子供用」と分けられているかというと、現場のプログラミングをいきなり子供が学ぶのは、結構キツイからだと思います。 その解決策として、ビジュアルプログラミングが採用されるのが多くなっている感は正直あります。 確かにタイピングがいらないし、英語もいらないし、文字もほとんど打たなくて良いし、高度な文章理解能力もいらないし、リファレンスもいらないので、だいぶハードルが下がる。 良いことです。

ビジュアルプログラミングは幼少期からITを先取りするためには必須に近いと思います。 先取りは世界的にどんどん早くなっています。取り組んでいる内容は、PDF: 諸外国における プログラミング教育に関する調査研究(文部科学省)にまとまっているので、読んでみると面白いです。 非常に良い資料で、この資料を読むと、日本の子が何をすべきかすぐにわかると思うし、大人は回答が出せないといけないと思います。 特にインドが凄まじくて、小学生で日本の大学生レベルに到達しそうな勢いです。 これに追いつくのは普通にやっていたら絶対無理なので、ビジュアルプログラミングによる先取りは有効と思います。 日本のように英語との親和性が低い国だと、特に。

ビジュアルプログラミングについて一番まとまってるのは Wikipedia のビジュアルプログラミングのページ と思うのですが、 このページは、実際どれが一番流行っているか、どのような製品/サービスがあるかは載ってません。 そこでビジュアルプログラミングを想定した製品/サービスごとに、最も使われているものを調べ、触ってもみました。

世界のビジュアルプログラミング教材

1. Code.org

現在ビジュアルプログラミングで最も有名なのは Code.org です (4億人〜)。 歴史は浅いですが、世界中の名だたる企業の支援により、2013年から一気に伸びています。 Hour of Code という仕組みでイベント的に行われるせいもあってか、Google Trends などで調べると、まだ後述する Scratch のほうが有名です。 Code.org は実際のプログラミングでも利用頻度の高い JavaScript コードに変換でき、体系的に学べるのが良いところです。 私はとてもよくできた教材と思っています。



2. Minecraft

2番目に有名なのは Minecraft です (1億2000万人〜)。 Minecraft 自体はただのゲームなのですが、ビジュアルプログラミング言語や Python などの実用言語と連携して遊べるので馬鹿にはできません。 ただ今のところプログラミング言語との連携は、設定も環境も面倒なのは難点かなあ。 「プログラミング思考」を学ぶためや「PC/IT製品に慣れる」ために利用するなら、初期導入としては面白いかも、とは思います。 ただプログラミングと関係ないところでハマってしまう時間が増えすぎるので、私は使わないかなあ。 PC版とiOS/Android版では値段が違い、iOS/Android版のほうが安いです。教育用バージョンも (一応) あります。


Google Play で手に入れよう


3. Scratch

歴史が長く、3番目に有名なのは MIT の開発した Scratch です (3000万人〜)。 日本だとScratchが一番よく使われてる気がします。 サンプル数が非常に多く、様々なサービスや製品と連携しやすいのが利点ですが、導入説明が少ないのは難点です。



4. Codemao

4位は中国のWebサービスである Codemao です。 利用者数は具体的な数字が書かれていて、執筆時点では中国で7120校の採用があり、2063万人が使っているそうです。 2015年3月に会社設立でこの速度は、恐ろしいものがある。 登録制なので中は見れませんが、ハーバードから教員を招いていて、カリキュラム付きの専門コースがあるみたい。 本格的だなあ。

ところで中国の 0-14 歳人口は 2.35 億人ほどと言われていますので、中国の子供たちのうち最低 8% がこの高度な IT 教育を受けているという事になります。 もっと現実的に考えると、中国は沿岸部の人口が51%と言われており、今も増えているものと思われます。 これを考慮すると、沿岸部の 20% くらいの子供たちが最先端教育を受けていると予想できます。
数字を見ていても、中国は「勝つための教育」をしている国だとよくわかります。 日本もようやくプログラミング教育が始まりますが、香港ではプログラミングが第三外国語になっていますし、中国も凄い速度で進化しています。 世界の速度感、規模感、クオリティがいかに凄いかよくわかるかと思います。



5. mBot

5番目に有名なのは、おそらく mBot です (450万人〜)。 中国発のロボット製品で、そのコーディングにビジュアルプログラミングを利用しています。 最近は体を使ったりロボットを使って学ぶ、フィジカルプログラミングや物理コンピューティングという言葉が出てきましたが、その中で1番有名なのが mBot になると思います。 mBotは日本ではなかなか手に入れることが大変なのですが、まあまあ安い割に機能が豊富なのが特長です。 ソフトバンクが色々やってるみたいなので、そのうち簡単に手に入るようになるかも。 今のところ mBot (左) と、拡張版の mBot Ranger (右) の、2つのバージョンがあります。




6. レゴ®マインドストーム, レゴ®ブースト, etc.

6位はレゴシリーズです。 レゴの人口は4億人と言われていますが、ビジュアルプログラミングのできるレゴ®マインドストーム のユーザは 200万人 です。 思っていたより少ないのは知見でした。 レゴ®マインドストームは結構お高いのですが、最近はレゴ®ブーストという廉価版も出ています。 レゴ®ブーストmBot は同じくらいの値段なので、どちらを取るかは難しいところ。 レゴは他にも教育機関向けの WeDo などのシリーズもあります。




7. micro:bit

7位は micro:bit です (100万人〜)。 様々なセンサーを使って遊べる製品です。執筆時点ではバルク品だと2,160円で購入でき、日本でも簡単に手に入ります。 ケーブル類や電池類を買おうとすると意外と高いので、正規品で良いように私は思います。 いずれにしても非常に安いのに、かなり色々なことが、非常に簡単にできるのが特長です。 Python コードに変換できるのも良い点だと思います。





番外

ビジュアルプログラミングに閉じず、教育に利用できる製品としては Raspberry Pi (通称: ラズパイ) も有名です (1100万人〜)。 ラズパイは小型PCとも言えるし、拡張可能なIoT製品とも言えます。 似たような製品はたくさんありますが、知名度の要因は、手頃な価格とLinux OSが動くことにあると思います。 Raspberry Pi は一定以上のレベルがあれば良い教材とは思いますが、完全な素人の子どもにはハードルが高いです。 利用用途のよく似た micro:bit のような手軽さはありません。 またどのように使うかで、パーツも選ばないといけないし、購入の仕方も大きく変わってくるので、教える側も買う時に相当悩むでしょう。 Raspberry Pi そのものにはビジュアルプログラミングは付いていませんが、組み合わせることはできるので、いちおう候補には挙がるのかな…。



Linux を学ぶなら Raspberry Pi のほうが良いですが、電子工作を意識したビジュアルプログラミングをしたいなら、Arduino は良い候補かも知れません (3000万人〜)。 Raspberry Pi より多いのは意外でした。 BlocklyDuino というエディタでビジュアルプログラミングができるのは、Raspberry Pi より良いところです。

Arduino は様々なセンサーキットが売られているのですが、種類があり過ぎて選ぶのが大変になってる。 欲しいものだけ選ぶほうが良いかも知れませんが、慣れている人じゃないと相当大変だろうなあ。 また Arduino でも Raspberry Pi でも、電子工作はいざ製品を組み合わせようとすると、どうやっても電流や抵抗の知識が必要になります。 私のようなソフトウェア人間だとここが面倒に感じます。 ソフトウェアな人は電流や抵抗を意識する必要がまったくないので、習う必要性をあまり感じない。 このへんがソフトウェア/ハードウェアの適正を分ける境界線なのかも。 やはり敷居は高いと思います。




8. Blockly

8位以降は正直よくわかりません。日本に閉じていると、今のところ数万人の採用が限界なので、やはり海外製のほうが規模は大きくなります。 何となくの予想では Blockly が有名そうです。 BlocklyCode.org の前身とも言えるサービスなので、今のところ Blockly そのものを触る必要はなさそうですが、Google らしさをどこかで出してくる可能性はあります。 その1つの可能性は、Project Bloks です。



9. p5.js (Processing)

コードを書かないことがビジュアルプログラミングの前提な気もするのですが、ほんの少しのコードでプログラミングできる言語はたくさんあります。 その条件で一番有名なものは p5.js でしょう。 コーディングのファーストステップとしては、非常にわかりやすい言語だと思います。 なぜ取り上げたかと言うと、採用数が大きそうで、Code.org が変換する JavaScript コードとも親和性があるからです。 ビジュアルプログラミングを学ぶ上では、このような発展性の考慮も重要と思います。




その他たくさん

他にもたくさん製品/サービスがあるので、特に参考になったリンクをまとめます。 ただ私は発展性があり採用経験も豊富な、上記製品/サービスが良い気がしている。 色々理由はあるんですが、日本は後進国なので、間違った脚色を入れたものではなくきちんとプログラミングそのものを学ぶ教材を採用して欲しいんですよねえ。
あまりにも製品/サービスが増えてきたせいで、全部取り上げるのは煩雑になるだけに感じます。 性能が良くて安いとか、高機能で汎用性があるとか、何らかの特長がないと採用は難しいと思う。 iOS/Android 上で無料で使えるアプリもだいたい試しているつもりですが、特におすすめはないかな。 色々触ってみて感じるのは、適当にガチャガチャやったり真似してればできてしまうものと、 ループを使ってできると簡単というものは頭の使い方がぜんぜん違う点です。 前者はものづくり、後者はプログラミングなので、後者を意識したもののほうが良いんじゃないかな。

私が特に面白そうと思ってる製品/サービスを取り上げてみると以下です。 規模がわからないので大きくは取り上げないですが、特長が際立っているものです。



日本のビジュアルプログラミング教材

以降は日本で利用されている言語も紹介したいと思います。 製品に関しては上記リンクを参照頂くとして、無料のものだけを取り上げます。

10. ドリトル

おそらく日本製+無料で一番使われているのはドリトルで、小学校での導入事例もあります。 日本語プログラミングとビジュアルプログラミングの両方ができるのが特長です。



11. プログラミン

プログラミンは文部科学省が作った、お手軽なビジュアルプログラミング言語です。 Flashのため更新予定はなさそうなのが残念ですが、私はよくできたツールだと思っています。



12. MOONBlock (前田ブロック)

MOONBlock は、秋葉原リサーチセンターで開発された言語です。 前田ブロックという名称の時期もあったようです。 UIが独特。

13. Viscuit

Viscuit は、ビジュアルプログラミングとはまた毛色が違った、簡易お絵描きツールです。 最近のUIとはかなり異なっていますが、ビジュアルプログラミングの一種とは言えそう。 海外にもお絵描き専用のビジュアルプログラミングはいくつかあります。



ビジュアルプログラミング以外にも、ゲームで何となくプログラミングを学ぶアプリや教材もあります。 短時間ならゲームも良いと思います。 ただ最終的にプログラミングに繋げるためには、コーディングを想定した学習にする必要がある。 そう考えるとビジュアルプログラミングは必須だし、シームレスにコーディングに移行できる基盤も必須に感じる。 将来を見据えてやるかどうかの差は大きいと思います。

2019年8月13日火曜日

Web Worker の使い方ざっくりまとめ

Web Worker は全然使ったことなかったのですが、 使っているライブラリを触って苦労したので、最低限の使い方をまとめます。 まずは以下のコードが基本。これは main.js から worker.js を Web Worker として呼び出す例です。 呼び出したときの処理として load, proc の 2 つを定義しています。
// main.js
var worker = new Worker('worker.js');
worker.postMessage({type:'load'});
worker.addEventListener('message', function(event) {
  if (event.data.type == 'result') {
    document.getElementById('foo').value = event.data.a;
  }
});
worker.postMessage({type:'proc'});

// worker.js
self.addEventListener('message', function(event) {
  if (event.data.type == 'load') {
    // load
  } else if (event.data.type == 'proc') {
    event.data.type = 'result';
    event.data.a += 1;
    postMessage(event.data);
  }
});
worker.js 側では addEventListener で message イベントハンドラを Listen して通信を待ちます。 通信は postMessage 関数で行います。 処理は非同期に行われるため、結果を受け取って何かをするには、 worker.js 側で postMessage 関数を呼び出し、 main.js 側でも message イベントハンドラを Listen にすることで実現できます。


複数の処理を Web Worker で処理させる

だいたいの仕組みはこれで良いのですが、 複数のメッセージを送信し合ったり、複数の処理を行う場合、少し面倒です。 proc 関数の結果を受け取って、さらに proc1, proc2 を実行するにはどうすればいいでしょうか。 これは main.js を以下のように変えれば良さそうです。
// main.js
var worker = new Worker('worker.js');
worker.postMessage({type:'load'});
worker.addEventListener('message', function(event) {
  if (event.data.type == 'result') {
    if (event.data.id == 1) {
      document.getElementById('foo').value = event.data.a;
    } else {
      document.getElementById('bar').value = event.data.a;
    }
  }
});
worker.postMessage({type:'proc', id:1});
この例で注意しないといけないのは、main.js 側の message イベントハンドラを複数用意したとしても、 proc1, proc2 を実行する条件がわからないということです。 DOM ノードを渡すことなどもできないので、postMessage 関数を呼び出す際に、 id などの何らかの情報を付ける必要があります。

その時に重要なのが、worker.js をライブラリとして提供する場合、 worker.js の postMessage 関数を定形データにはできないということです。 定形データにしようとすると id を返り値として返却することができず、 どのノードに対して処理をするかわからなくなってしまいます。 どうしても定形データとして処理したい場合、worker.js 側で id に関する処理を記述しなければいけないと思います。 ここで少しハマりました。


大量の DOM ノードを Web Worker に投げる

もう1つの問題は、大量の DOM ノードを worker に投げて、その結果を DOM ノードに反映させる必要がある時です。 worker は DOMノードにアクセスできないので 情報を渡すことができません。 代わりに message イベントハンドラは外側のスコープのデータを見れるようです。 なので以下のように ID 渡しで書けます。
// main.js
var worker = new Worker('worker.js');
worker.postMessage({type:'load'});

var nodes = document.getElementById('hoge').children;
worker.addEventListener('message', function(event) {
  if (event.data.type == 'result') {
    if (event.data.id == 1) {
      nodes[i].value = event.data.a;
    } else {
      document.getElementById('bar').value = event.data.a;
    }
  }
});
for (var i=0; i<nodes.length; i++) {
  worker.postMessage({type:'proc', id:i});
}


結果をマージする → たぶんできない

結果をマージしたい場合にはどうすれば良いでしょうか。 …どうやらこれは無理な気がしています。 普通は以下のように Promise を使って終了判定すれば良いのですが、 Web Worker の場合は worker の postMessage の終了ではなく、 その結果を受信した後に処理したものすべての終了状態を知らないといけない。 でもそこにフックをかけるのは無理っぽい。 イベント駆動型だから仕方ないか。 最後にマージしないでも済むように、事前にノードを作ったりして、 非同期になるようにコードを書き換えるしかないのでしょう。
var procAll = new Promise(function() {
  for (var i=0; i<nodes.length; i++) {
    worker.postMessage({type:'proc', id:i});
  }
});
Promise.all(procAll).then(function(results) {
  :
});


はー。JavaScriptまったくわからない。

2019年8月9日金曜日

フリゲ紹介: 木陰のアンチクリスト

木陰のアンチクリストは1〜2時間でクリアできる、パズル系の探索RPG。



ゲーム内ではストーリーはあまり明らかにならず、すぐに探索が始まるタイプの作品ですが、説明文には以下のように書かれています。
大好きな師匠を助ける為、「封印の樹海」の最奥に乗り込んだ魔法少女チコリー。行く手を阻むのは、沢山の謎や危険な魔物達。そして教会が派遣した処刑人。二人は無事に家へ帰る事が出来るのでしょうか。そして、チコリーの小さな想いの行方は――。
若干の百合成分を含んでいますが、特に気にならないゲームです。 ゲーム自体はよくある探索RPGらしいシンプルなシステムになっています (下)。



普通の探索RPGと異なるのは、想定プレイ時間は1〜2時間と書いてあるけど、ボス (左下) が強く、短編のわりに歯ごたえがあるという点です。 あまり主人公たちのステータスが弄れないので、装備やスキルで頑張ることになるのですが、パズル要素がかなり強い。

謎解きなども凄くしっかり作られていて、例えば右下のパズルとか、フリゲたくさんプレイしてるけど、あまり見たことなくて凝ってると思いました。



たぶん1〜2時間よりは時間が掛かると思う。裏ボスを倒そうとすると凄く強いので、なかなか大変です。 短編でも歯ごたえがあって、とても面白かった作品でした。

フリゲ紹介: 細胞神曲

細胞神曲は、フリゲ2018で4位だった作品。 私も遅ればせながらプレイしましたが、とても面白い作品でした。



最初は伝奇ミステリーかな?と思う始まり方で、Chapter1でもやや難しめの謎解きになっていました (左下)。 そこから話が急展開し、気付いたら主人公の​​ 阿藤 春樹 は囚われの身になってしまいます。 そこで様々な人と出会うことに (右下)。



囚われてからは牢獄からの脱出を図るゲームになります。 バイオハザード系の探索アクションと謎解き脱出ゲームが融合したような、非常に面白い作品になっていました (左下)。 グロ系は普通にあるのでR指定の注意は必要ですが (右下)、様々なミニアクションがあって面白かったです。 ボリュームもかなりあってクリアには時間が掛かったのですが、面白いので一気にプレイしてしまいました。



Chapter7まではノーヒントで行けたのですが、Chapter7の謎解きは難しく、ヒントを見てしまいました。 ラストに近付くほど謎解きも難しくなります。 そしてクリアしたは良いのですが…評価D。完全クリアの道は遠いです。 プレイしている時にも様々な分岐の可能性には気付いていましたが、実際かなりたくさんの分岐があるようです。 様々なEDもあるようで、凄く作り込んでるなあという印象を受けました。

そして攻略サイトを見ていると、完全クリアを目指した場合には、まだまだストーリーには続きがあるようですね。 画像を見てると…なんか凄く面白そう… (未プレイ)。 評価Dでもとても面白い作品でしたが、いずれ完全クリアもやってみたいです。

2019年8月3日土曜日

SVGをHTML上で表示する時の注意点色々

SVGをHTML上で表示する時にいつもハマってるので、自分用に注意点をまとめます。

1. embedしたい時には img/object/embed/iframe タグの4つが使える

こんな感じで書く。
<img src="/img/test.svg" width="300" height="200" />
<object type="image/svg+xml" data="/img/test.svg" width="300" height="200">
</object>
<embed type="image/svg+xml" src="/img/test.svg" width="300" height="200">
</embed>
<iframe src="/img/test.svg" width="400" height="300"></iframe>
img タグが手軽。 ただどれでも良い訳ではなく、SVG 内の要素にアクセスしたい時 (例えばクリックイベントを使いたい時など) には object を使わなくてはいけない。 embed は SVG がプラグインなしでは表示できなかった時代のブラウザ対応に使うので、最近は使わない。 iframe も width/height の扱いや速度に制約が多いので、普通は使わないと思われる。


2. SVG を縮小/拡大表示するためには viewBox を使う

object タグで呼び出し、SVGを縮小/拡大表示するためには viewBox を使う必要がある (img タグで呼び出す時はなくても大丈夫)。 SVGファイルの中身は以下のように書かないといけない。 viewBox の値は、width, height と同じ値を書いておけば普通はイケる。この指定がないと縮小表示してくれません。
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 400 300" width="400" height="300" ...>
  ...
</svg>
viewBox の指定さえすれば、あとは 1 と同じ方法で SVG を呼び出すだけ。

3. width, height の指定は px にすべき

自動生成された SVG ではたまに width, height を px 以外で設定していることがある。 この SVG は直リンクで表示するときは良いのだけど、同階層で複数の img タグを呼び出す (下例) と表示サイズが粉々になるケースがある。
<style>
  .responsive { max-width:100%; height:auto; }
</style>
<div>
  <img class="responsive" src="1.png" width="1em" height="2em"/>
  <img class="responsive" src="2.png" width="2em" height="4em"/>
</div>
どういうことかというと、responsive クラスが悪さをする。 ブラウザは最初の SVG で max-width:100%; になるように em の指定を px にスケーリングし直し、div のサイズに画像をリサイズする。 そして以降の SVG も「そのスケーリングを使用して」表示する。 いつか挙動が変わるかも知れないけど、width, height の em のサイズが異なると、これによってスケーリングが崩壊する。 width, height は px にすべきではないかな。

4. 外部 SVG を読み込んで色々操作する (1)

地味にベストプラクティスがわからないのがこれで、CORS 関連による変更でよくわからなくなってます。 JavaScript 主体で書くなら以下が一番良いと思う。

ポイントは (1) text/html として SVG を読み込むことで、HTML 関連のメソッドを使えるようにする。 (2) SVG のルート要素を探索して CDATA のノイズを消すことです。 この方法以外の読み込みだと、SVG 内部で getElementById も querySelector も使えないで疲れる。
fetch('test.svg')
.then(response => response.text())
.then(text => {
  const parser = new DOMParser();
  return parser.parseFromString(text, 'text/html');
}).then(html => {
  var parent = document.getElementById('parent');
  var svg = html.getElementsByTagName('svg')[0];
  parent.appendChild(svg);
  var abc = svg.getElementById('abc');
});


5. 外部 SVG を読み込んで色々操作する (2)

もう一つの実装方法は、object で SVG を読み込んだ後に、contentDocument で中身を操作する方法です。 ちなみに getSVGDocument() でアクセスできるブラウザもありますが、deprecated なので contentDocument を使いましょう。 注意点としては、SVG を読み込んだ後にしか操作できないことです。 そのため、例えば以下のように実装します。
<object type="image/svg+xml" data="/img/test.svg"
  onload="init(this)" width="300" height="200">
</object>
function init(obj) {
  console.log(obj.contentDocument);
}
addEventListener より onload 属性で書いたほうがすっきりします。 1と比較したときの利点は、SVG 内の ID 重複が起きないことと、onload の非同期処理が少し楽になることです。 欠点としては、この方式で動かす時には HTTP/HTTPS 経由で動かさないと、object.contentDocument = null になってしまいます。 何もエラーが出ず null になるので、これに長時間ハマったことがある。

さらに object 要素は data属性を付与した後でイベントを待っても onload イベントが発生しないことに注意する必要があります。 他の要素ではそのようなことは起きません。data属性を付ける前に onload イベントを付与すればきちんとイベントは補足できます。 このような細かく複雑な仕様が至るところにあって、意外と SVG の処理はハマります。

6. 公開時は SVG を simplify してファイルサイズを小さく

SVGのpathを簡略化するとファイルサイズがとても小さくなります。 いつもキーワードを忘れるけど、simplify / optimizer / cleaner あたりで検索すると良さそう。 いくつかツールがありまずが、割と使いやすいのが scour です。

7. 公開時は SVG を minify してファイルサイズを小さく

こちらは書く必要はないかも知れませんが、minify するとさらにファイルサイズを小さくできます。 私は tdewolff/minify を使っています。

8. img タグと object タグの embed は表示動作が異なる

img タグではJavaScript が効かない違いは先にも述べましたが、他にも表示の仕方が何か違うみたい。 私もあまり良くわかってませんが、少なくとも以下の SVG の "Yo" が img タグだとうまくできない。 うまく表示できないタグそのものを弄れば何とかなるみたいだけど、何だろうこれ。

Yo""無線で文字列を送信ボタンAが押されたとき


9. SVG の余白を削除する

複数の SVG を並べて表示するときなどに、SVG の余白が邪魔になるときがある。 SVG の余白を削除するのは Inkscape を使うのがおそらく一番楽です。 メニューの「ファイル」→「ドキュメントのプロパティ」→「ページサイズをコンテントに合わせて変更」を実行すると、余白をゼロにしてくれる。

10. SVG の PNG 書き出し時には外部リンクに注意

SVG を img 要素を介して canvas に書き出す処理 は日常的に使われます。 しかし Web フォントを使っていると、セキュリティの問題から外部リンクが読み出されない問題が発生し、フォントが適用されない問題が発生します。 Web フォントに限らず、何らかの外部リンクは同じような結果になります。 対処法としては、外部リンクの中身を dataURI スキーム形式に変換し, SVG 内に style 要素として埋め込む必要があります。 日本語フォントはサイズが大きいので、当然ながら超重いです。 canvas の解像度を上げて書き出すほうがマシだと思う。

最近は少しでも詰まったらメモっておくのが一番早い。