JetBrains の EduTools で課題を作ってみた(ある迷走者の手記)

# EduTools とは？
JetBrains 社の IDE 用プラグインで、学習コンテンツの利用と作成が可能になる。

基本的には、よくあるプログラミング学習コンテンツと同じように、説明を読みながら出された課題を解決するようコードを調整していく。
その他、知識の確認をクイズで行うこともできる。

![プラグイン説明の画面例](https://plugins.jetbrains.com/files/10081/screenshot_788a39de-16ce-462d-94fb-7b6e929a241c)

IntelliJ IDEA(Java向けIDE)と PyCharm(Python向けIDE)の Education バージョンで使われている。(他 IDE にも入れられる)

# 最小構成で作ってみた
1. コースを作る → レッスンが1つ含まれている
   - 「ファイル」→「学んで教える」→「新規コースの作成」
2. コース情報を入力
   - ダイアログ内の項目を適切に設定
3. レッスン情報を修正
   - lesson-info.yaml に custom_name として日本語レッスン名を追加
4. タスクを追加する
   - レッスンを右クリックし「タスク」選択後、種類を選んで名前を決定
5. タスクの内容とコード(正答例、テスト)を書く
   - task.md にタスク説明(課題)を Markdown で記入(ファイル拡張子変更で HTML も可らしい)
   - tests/test_task.py に確認用テスト(正しいコードで実行すると pass になるテスト)を実装
   - task.py に正答例コードを実装し、回答させたい部分を選択→右クリック→「解答のプレースホルダーを追加」でダミーコードに置き換え
6. プレビューでチェック
   - プロジェクトペインで右クリック→「Course Creator」→「コースプレビューの作成」
   - コース情報ダイアログが表示されるので内容を確認して「開始」を押すと新ウィンドウでコース内容が表示される(進捗はウィンドウを閉じると破棄される様子)

# (妄想版)コース作成ツアー
1. コースを作る 『オレオレ プログラミング入門コース』
2. セクションで分ける(入れ子にできないので、カテゴリ分けのような感じ？)
   - 『たぶん読み飛ばされる 理論編』
   - 『途中で挫折する 実践編』
3. レッスンかフレームワークレッスンを並べる(これらも入れ子にできない)
   - 理論編
      - 『プログラムとは？』
      - 『作るための道具(開発環境)』
      - 『基本構成要素』
   - 実践編
     - 『世界に向かって「こんにちは！」と叫ぶプログラム(文字の表示)』
     - 『繰り返すだけなら鸚鵡にもできる(文字列の入力)』
     - 『必ず勝てるジャンケンゲーム(条件分岐)』
4. タスクを作成していく
   - 公式ページの説明に記載されていたポイント(超意訳)
      - コードで実装すべき課題(テストをパスさせる条件)を明確にする
      - テキストの装飾(マークアップ、タグ)はキッチリ書く(閉じ忘れ注意)
      - タスク内で見せるファイルは最小限に絞る
      - リンクとテストは全て動作を確認する
      - テストは正しい回答に対して「成功(pass)」となるよう構成する
      - テストで回答に誤りがある場合に詳しいフィードバックを表示するのは良い作法である
   - ジャンケンゲームだと…
     - 『骨組を作る(入力なし、自分と相手の手と結果を文字列表示)』
       - 骨組に print文を並べておき、出力文字列の一部を課題とする
     - 『勝敗判定を実装(自分と相手の手を引数にして結果を返す関数を実装)』
       - 関数呼び出しの部分をプレースホルダにして入力してもらう
       - 判定関数の内容もキーワードや文字列の一部を課題にするのはアリかも？
     - 『自分の手の入力を実装(入力を確認して不正なら再入力を促す)』
       - 無限ループの「while」か「True」をプレースホルダに。
       - 入力内容チェックの条件判定を逆にしておいて「not」を入れさせる？
     - 『自分の手に負けるよう相手の手を決定』
       - 返す値をそれぞれプレースホルダにする？
5. プレビューを確認する
6. 配布用にパッケージする
   マーケットプレイスに公開すれば億万長者か？！(喜)
   …え、内容チェックある？フォーム記入とかも？
   はい、ドキュメント読んで出直します…って英語かよっ！！(号泣)

# パーツの細かい違い
## レッスンとフレームワークレッスン
- フレームワークレッスンはタスク説明に自動的に番号が付く(『タスク 2/7：if 文』のように 現在番号／全タスク数)

- 説明(英語)によると、フレームワークレッスンは『共通するコードベースを使い、複数のタスクで構成されるレッスン』という位置付けらしい

## タスクの種別
### チェック有り
- コーディング演習
  - Edu(Edu)：テストによるチェック(テストコードを書く)
  - 出力(Output)：出力内容によるチェック(テストコード自体は書かない)

- クイズ出題(選択して回答)
   - 複数選択(Multiple-choice)：選択肢から正しいものを選ぶ(名前に反し、単一選択もコレを使う)
### チェック無し
「理論(Theory)」と「IDE」はチェック無し。
ただし、「実行」ボタンを一度は押さないと「次へ」ボタンが出ない様子。

「IDE」は「ヘルプ → IDEの学習」みたいな課題を作れるかと思ったら、そういう方法(UI付近にポップアップ出す等)は説明を見付けられなかった…

# ハマった点
- タスクごとに 1ファイル(大抵は task.py か main.py)は表示させる。
  タスク内の全ファイルが非表示だと、タスク解説が表示されず、達成できない…

- 途中でブロックするコード(入力用の input関数など)があると、デバッグ実行ペインの内容が GUI でなく、pdb コンソールになってしまう場合がある？

- フレームワークレッスンで共通コード用にタスクと同レベルにフォルダを作り、コードファイルを置いて tests/test-task.py で `from ...shared1 import SharedClass1` のようにしたらエラーで怒られた…
  → 処理時のルートフォルダより上のパスのインポートはダメらしい。`sys.path.append("../")` で迂回できたけど…
  → 正当な対策(もしくはフォルダ構成)をご存知の方は、よければご指摘ください。

# 最後に
Web 検索で日本語リソースを(公式以外に)見付けられず、泣く泣く英語を読みながら試行錯誤した一日分の記録(≒消費した時間達のダイイングメッセージ)。
誰かの福音になる微小な確率に賭けるため公開。

順当な予想としては以下の通り。
- ストレージの肥やし：98%
- 忘れた頃に自分で検索して再発見して泣く：1.99%
- 誰かの役に立って「いいね」してもらえる：0.01%