読者です 読者をやめる 読者になる 読者になる

.styをTeX Liveに入れる方法(root不要)

ユーザ権限で行いたい。

この場合、~/texmfに置いておけば自動的に毎回読んでくれるらしい。

TeX Live - ArchWiki

たとえば CTAN: Package bytefield これを入れるときは、

$ mkdir ~/texmf
$ unzip bytefield.zip
(幸いこの中にはコンパイル済みの.styが入っていた)
$ cp -r tex/ ~/texmf
$ tree ~/texmf
/home/ishikuro/texmf/
└── tex
    └── latex
        └── bytefield
            └── bytefield.sty
(使えるかどうか確認)
$ kpsewhich bytefield.sty
/home/ishikuro/texmf/tex/latex/bytefield/bytefield.sty

あとはドキュメントに従って\usepackageなりするとよい。

pngとかjpgをplatexで使う(debian jessie)

注意: この方法でpngを貼ると、PostScriptプリンタでの印刷でとても時間がかかるようになる。パワポで作った図表はできればpdfで出力して貼り込むのがよいと思う。

$ sudo apt install texlive-lang-japanese latexmk

~/.latexmk

#!/usr/bin/perl
$latex         = 'platex %O %S';
$bibtex        = 'pbibtex %O %B';
$dvipdf        = 'dvipdfmx %O %S';
$pdf_mode      = 3; # use dvipdf
$pdf_previewer = "evince"

files:

main.tex
figure/
    a.png
    b.png

main.tex

...
\usepackage[dvipdfmx][graphicx]
\graphicspath{{./figure/}}
...


\begin{figure}
  \includegraphics{a.png}
\end

このままだとエラーになる

$ latexmk main.tex

runpopen command not allowed: extractbb

extractbbの許可

$ sudo cp /usr/share/texlive/texmf.cnf /etc/texmf/texmf.d/90extractbb.cnf

90extractbb.cnfにextractbbを追加

shell_escape_commands = extractbb,bibtex,bibtex8,kpsewhich,makeindex,mpost,repstopdf,
$ sudo update-texmf
$ latexmk main.tex

これで画像が自動で挿入される。いまどきはepsとか用意しなくていい。

WebからFPGAの回路を記述できる簡易IDEを作った

これはAizu Advent Calender 2015の21日目の記事です。
前は@yutoppさんです
次は@about_hiroppyさんの予定です。

はじめに

会津大学の学生のishikuroです。こんにちは。

需要がありそうだったので(確信)、育毛のプレゼンを書くつもりでしたが、今日12月21日は私の0x1C回目の誕生日であり、この先の一年の悪い暗示になってしまいそうなのと、優先的に紹介しないといけないものを思い出したのでやめます。育毛について聞きたい方は直接ご連絡ください。ちなみに誕生日についてはささやかなアピールです。

今日は「WebからFPGAの回路を記述できる簡易IDE」をyattan氏をはじめとした研究室のメンバーと一緒に作った経緯をお話しようと思います。

f:id:ishn:20151221174158g:plain


youtu.be

Webインターフェイスから回路を記述し、サーバーに接続されたFPGAボードに書き込みができます。

経緯

私の研究室では毎年グループワークの訓練も兼ねて、研究とは別に組み込みっぽい工作をしており、オープンキャンパスの日に研究成果と一緒に展示しています。

f:id:ishn:20151221162012p:plain
画像の出典: 研究室のpublicなサイト

今年の私の班は「高校生向けにコンピュータハードウェアの設計体験ワークショップを開く」というのに挑戦しました。私含め院2年生2名, 学部3年生4人で実行。



画像の下の方に見えてる工作も、ものすごいプロジェクトではあるんですが今回はチラ見せだけです。

このワークショップのオマケとして、ハードウェア記述言語のことも知ってもらえるかもしれないと思って作っていたものがあります。それが、ハードウェア記述言語のコンパイラおよびFPGA書き込みツールの、簡易IDEです。Arduino, ProcessingのIDEからインスパイアを受けてます。教育用として作りましたが、これが応用次第で「リモートからFPGAの回路を記述できるシステム」になるんです。

ishikuro/asolide · GitHub

githubに反映されてない部分もありますが、班内で分担して学部生も平等にコードを書きました。

ワークショップ当日は、来場者に論理ゲートの工作で4bit adderを作ってもらい動作を確認してもらいます。その後、工作と同じ内容のハードウェア記述を本IDEで実演し、同様な動作をすることを見てもらうつもりでした。しかし、演習内容を吟味した結果、来場者にとって詰め込みすぎになって疲れてしまうんではないかということが分かってきました。結局このシステムは当日は展示だけに留まっています。

機能

できること

NSLで回路を記述できる

世界で初めてハードウェア記述言語を提案したのは実は日本のNTT研究所でした。それまでは模造紙に論理を描いていたそうです。

今回のシステムでは国産ハードウェア記述言語の末裔、NSLを使っています。業界標準のVerilogHDLよりも抽象的に書けるのが利点です。

ちなみに今回のシステムに似たアイディアとして、NSLのオンラインコンパイラがあります。
NSL CORE TRIAL USE

このハードウェア記述言語で、GPIOの動作を記述していくことになります。

書き込みボタン以外なにもついてない

Altera等のFPGAメーカが提供するIDEEclipseよりも巨大で、周辺ツールが膨大になっています。しかし、そこから回路の論理設計のエッセンスだけを抽出したいと思い、ArduinoやProcessingのIDEのようなものを提案しました。書き込みボタンを押すと、回路設計のための様々なステップを隠蔽して、FPGAに書き込みをします。

FPGAではGPIOを制御

GPGPUのようなアクセラレータとしてFPGAを使う場合はPCIeとかに接続するのですが、今回はGPIOの操作だけを行えます。オンラインのArduinoみたいな感じです。

仕組み

Node.jsがメインのフレームワークです。

フロントエンド

入力したソースをサーバー側にPOSTして、コンパイルのログをsocket.ioで受け取ります。

複数ウィンドウを開いた状態で書き込みボタンを押すと、古いほうを中断してくれます。

バックエンド

以下のフローを子プロセスで実行します。

逐一、ログをフロントエンド側にsocket.ioで送ります。

FPGAの書き込みが終わったら、GPIOと記述した回路の動作が始まります。

未実装

今後の展望

XeonFPGAが載るなんて夢のある話もありますよね。きっと将来、AWS上でFPGAアクセラレーションがかけられるインスタンスも登場するんじゃないかと予想しています。

今回作ったやつは、書き込みこそUSB Blasterですが、実行時のFPGAとのインターフェイスはGPIOしかありません。サーバーとFPGAボードをPCIeと接続して、FPGAのリソーススケジューラみたいなのを実装すれば、もしかしたらクラウドFPGAの簡易的な実現と言えるかもしれません。

また、現在の構成だけでも、ArduinoのようなIoT的な使い方はできそうです。

余談ですが、いつかgithubのような場で回路関連のツールがどんどん出てくる時代になってほしいです。gemとかnpmみたいなコミュニティベースのエコシステムは一切ありえない回路設計業界ですが、オープンソースハードウェアの潮流がこちらに目を向けてくれたらと思ってます。

termdownでポモドーロテクニック

30分とか短時間で集中して作業するのが効果的らしい。まわりの人も結構やってたので私もやっている。termdownというツールが良かったので備忘録として書く。

ポモドーロテクニックとは - はてなキーワード

アジャイルな時間管理術 ポモドーロテクニック入門 | Staffan Noeteberg, 渋川 よしき, 渋川 あき | 本 | Amazon.co.jp

集中して仕事をこなすために、25分毎に時間を区切って仕事をする時間管理術。Francesco Cirillo氏が1992年、自身の勉強効率を上げるために考案した。

手順

1. 25分を1ポモドーロとし、やるべきタスクを1ポモドーロ刻み(25分毎)に分ける。
2. 25分間は、他の事は一切やらず、タスクに集中する
3. 25分経てば、5分間の休憩を入れる
4. 4ポモドーロ毎(2時間毎)に30分程の長い休憩をとる
5. 後は上記を繰り返す

ただし、いまいち良いアプリが無い。

欲しいキッチンタイマーアプリ:

  • 環境非依存
  • 変なイラストとかが入らない

探してみたところ、termdownというコマンドが要件を満たしていた。

インストール

python製であり、pipでインストールできる

sudo pip install termdown

使い方

termdown -a -b -c 10 --no-figlet 25m
  • -a, --alt-format: 付けないと、"24m 28s"みたいな表記になる
  • -b, --bliknk: 終了時目立つようにする
  • -c, --critical N: 最後のN秒を赤字にする
  • --no-figlet: デフォルトだとアスキーアートで表示されるのだが、場所をとるので表示しないようにできる

ターミナルのウィンドウを専有させて、文字サイズを大きめにし、Always on Topしておくと便利。

f:id:ishn:20151118104220p:plain

関連記事

ishikuro.hateblo.jp

React + TypeScript + Webpackの最小構成

このエントリは古い情報です。

今は typescript の代わりに flowtype も使えそうです。また、ブートストラップとしては create-react-app が提供されており、ここからカスタマイズしたほうが便利だと思います。

github.com


前回

ishikuro.hateblo.jp

の続き。前回のリポジトリを元にTypeScript版を作ってみたい:

GitHub - ishikuro/thinking-in-react-webpack-minimum at typescript

最終的なファイルツリー

.
├── dist
│   ├── bundle.js
│   └── index.html
├── package.json
├── README.md
├── src
│   ├── app.tsx
│   ├── tsd.json
│   └── typings
│       ├── react
│       │   └── react.d.ts
│       └── tsd.d.ts
├── tsconfig.json
└── webpack.config.js

今回もサーバーは立ち上げずにブラウザで直接ローカルのindex.htmlファイルを開いて動作を確認する。

前回と比較すると、型定義ファイル(typings/)とコンパイルオプション(tsconfig.json)が追加されている。

TypeScriptで記述

webpack中やvimプラグインで使われるので先にtypescriptのnpmを入れておく。

npm install -g typescript

.vimrc

" syntax highlightを有効にする
NeoBundle 'leafgarland/typescript-vim'
" typescriptのインデントを適切にする
NeoBundle 'jason0x43/vim-js-indent'
" コード補完や定義/参照へのジャンプをできるようにする
NeoBundle 'Quramy/tsuquyomi'
" .tsxもtypescriptとして扱う
autocmd BufNewFile,BufRead *.{ts,tsx} set filetype=typescript

型定義ファイルを追加

npm install -g tsd
cd src/
tsd query react --action install --resolve --save

コンパイル方法

TypeScript内でJSXやReactを扱うために、様々なハックが存在していたが、2015年7月ころにtypescriptがJSXをネイティブサポートしたために収束した。

  • typescript 1.6以上でコンパイルすればok, webpackで使う場合はnpm install --save-dev typescript@nextで入れる
  • 拡張子は.tsxにしておく
  • webpackでの利用方法や、Reactのコーディング方法はts-loaderのtestで提示されている。

babelの代わりにts-loaderを使う

npm install --save-dev typescript@next ts-loader

tsconfig.jsonを作成。(コンパイラオプションやリンカ的なものを指示するファイル)

{
  "compilerOptions": {
    "jsx": "react"
  },
  "files": [
    "src/typings/tsd.d.ts"
  ]
}

webpack.config.jsを更新。拡張子をtsxにして、ts-loaderを使うようにするだけ。(Option: コンパイル速度を上げるためにはexternal指定でreactをビルドに含めないようにする。html側で読み込む。参考: ReactとStylusをwebpackで使うための開発環境構築)

module.exports = {
  entry: [
    './src/app.tsx'
  ],
  output: {
    path: 'dist',
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['', '.tsx', '.ts', '.js']
  },
  externals: {
    react: 'React'
  },
  module: {
    loaders: [
      { test: /\.ts(x?)$/, loader: 'ts-loader' }
    ]
  }
};

(Option: dist/index.html reactを別ファイルで読み込む。)

<!DOCTYPE html>
<html>
  <head>
    <title>Thinking in React</title>
  </head>
  <body>
    <script src="../node_modules/react/dist/react-with-addons.min.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

src/app.tsxのサンプル。ポイントは、propsなどの受け渡しをinterfaceで行うこと。これだけでもだいぶ人に伝えやすくなると思った。

/// <reference path="typings/tsd.d.ts" />
import * as React from 'react';

interface Props {
  content: string;
}

class MyComponent extends React.Component<Props, {}> {
  render() {
    return <div>{this.props.content}</div>
  }
}

React.render(<MyComponent content="Hello World" />, document.body);

あとはコンパイルして確認

webpack
open dist/index.html

追記: ソースコードの変更点

全文はこちら: thinking-in-react-webpack-minimum/app.tsx at typescript · ishikuro/thinking-in-react-webpack-minimum · GitHub

import

/// <reference path="typings/tsd.d.ts" />
import * as React from 'react';

基本

interface PCRProps {
  category: string;
  key: string;
}

class ProductCategoryRow extends React.Component<PCRProps, {}> {
  render() {
    return (<tr><th colSpan={2}>{this.props.category}</th></tr>);
  }
}
  • propsやstateはinterfaceを作って明示する。extends React.Component<P, S>の形式でclassを作る。
  • JSXのプロパティも型があって、<th colSpan="2">もエラーになったので{2}としている。

ハマったところ

class SearchBar extends React.Component<SBProps, {}> {
  handleChange() {
    this.props.onUserInput(
        React.findDOMNode(this.refs.filterTextInput).value,
        React.findDOMNode(this.refs.inStockOnlyInput).checked
    );
  }

  render() {
    return (
      <form>
        <input
          type="text"
          placeholder="Search..."
          value={this.props.filterText}
          ref={"filterTextInput"}
          onChange={this.handleChange.bind(this)}
        />
        <p>
          <input
            type="checkbox"
            checked={this.props.inStockOnly}
            ref="inStockOnlyInput"
            onChange={this.handleChange.bind(this)}
          />
          {' '}
          Only show products in stock
        </p>
      </form>
    );
  }
}
  • React 0.13からDOMNodeの取得方法が変更になっている (React v0.13 - React Blog)
  • extends React.Componentから作る場合は、onChange={this.handleChange.bind(this)}のようにコールバックに.bindを自分で付けないとだめ

this.refsはランタイムで設定されるんだけど、TypeScriptコンパイラは分かってくれてないのでエラーを出す。

ERROR in ./src/app.tsx
(98,37): error TS2339: Property 'filterTextInput' does not exist on type '{ [key: strin
g]: Component<any, any>; }'.

ERROR in ./src/app.tsx
(98,54): error TS2339: Property 'value' does not exist on type 'Element'.

ERROR in ./src/app.tsx
(99,37): error TS2339: Property 'inStockOnlyInput' does not exist on type '{ [key: stri
ng]: Component<any, any>; }'.

ERROR in ./src/app.tsx
(99,55): error TS2339: Property 'checked' does not exist on type 'Element'.

解決方法は不明。一応、エラーを出しつつも.jsファイルは作ってくれて、意図した動作もするんだけど、とても嫌な感じ。

this.refsは使わないように、handleChange(e)から、e.target.valueみたいに取得する方針にして回避する。

Stateの初期化

interface FPTState {
  filterText: string;
  inStockOnly: boolean;
}

class FilterableProductTable extends React.Component<FPTProps, FPTState> {
  constructor(props) {
    super(props);
    this.state = {
      filterText: '',
      inStockOnly: false
    };
  }
...
  • getInitialStateはES6的な記述では使えない。代わりにconstructorを使う

JSONとかJSオブジェクトの読み込み

var PRODUCTS = [
  {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'},
  {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'},
  {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'},
  {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'},
  {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'},
  {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'}
];

interface Product {
  category: string;
  price: string;
  stocked: boolean;
  name: string;
}

interface FPTProps {
  products: Product[];
}

React.render(<FilterableProductTable products={PRODUCTS} />, document.body);
  • そのままだとPropsに流し込めないので、一旦interfaceでラップする。

Reactのチュートリアルをやってみた

完全に自分用メモ。

Thinking in Reactというチュートリアルを最小webpack構成で試した:

ishikuro/thinking-in-react-webpack-minimum · GitHub

React + Fluxの自分メモ

Webフロントエンドのプログラミングは、jQueryによる素朴なDOM操作から、AngularJSのような双方向バインディングへ移行してきた。しかしWebがコンポーネント指向に進むに従って、状態の管理が分散しがちであることが問題であった。

そこでFacebookが新世代のパラダイムを提案している。コンポーネント指向、仮想DOM、単方向バインディングなViewライブラリのReactを開発し、Fluxという単方向データフローのアーキテクチャを推奨した。

Fluxはアーキテクチャの名前であり、実装に規定はない。従ってgithubでもFluxアーキテクチャの実装が乱立している。今回はReactと、Flux亜種のひとつであるReduxという組み合わせを、Webpackを使って学習した。

これまで、自分でもAngularJS世代(双方向バインディング世代)のVue.jsで開発をしてきたが、きちんとしたデータフローを作ろうとすると自然とFluxっぽい設計になっていた。最上位VueコンポーネントをRootとして、状態はRootへ集約して、子コンポーネントが拾うユーザアクションは全てRootに伝える。Rootにビジネスロジックを持たせて、そこでデータを編集した状態を子コンポーネントに伝播させていってたりとか。Fluxはそういう手法を明確にレールにした印象。

React

Tutorial

Thinking in React

ファイル構成

webpack.config.js: src/*.jsをコンパイルして, dist/bundle.jsへ配置
dist/
  + index.html: bundle.jsをロードするだけ
src/
  + app.js: reactのimportと、実コードを書く

webpack.config.js

module.exports = {
  entry: [
    './src/app'
  ],
  output: {
    path: 'dist',
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel'
    }]
  }
};

dist/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Thinking in React</title>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

コンパイル方法

$ npm install -g webpack
$ npm install --save-dev babel-loader
$ npm install --save react
$ webpack
$ open dist/index.html

以下はThinking in Reactより。箇条書きは意訳でもなく、読書メモ的なもの。

Step 1: UIをコンポーネントに分割して名前をつける

  • UI要素を箱で囲っていって、名前をつけていく。それがコンポーネントになる。
  • "single responsibility principle" 1つのコンポーネントには1つの責務だけを負わせる。
  • information architectureに注意。JSONのデータモデルと視覚化されたUIがうまく一致するのが良い構造だ。

  • FilterableProductTable

    • SearchgBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow
      • ProductRow
      • ...
      • ProductCategoryRow
      • ProductRow
      • ProductRow
      • ...

Step 2: Reactで静的なバージョンを作ってみる

  • まずはインタラクションが無いバージョンを作ってみる。タイプ量が膨大だが考えることは少ない。
  • データモデルを描画を意識する。親コンポーネントから子コンポーネントへのデータフローにはpropsを使う。stateは現段階では使ってはいけない。それが必要になるのはインタラクションを追加するときだけだ。
  • 書くときはトップダウンでもボトムアップでも良い。小さいサンプルではトップダウンが楽だ。大きいプロジェクトではボトムアップにしてテストを書く。
  • このステップで作ったコードは、データモデルをあらわすコンポーネントライブラリになる。

Step2のコードを入れて、コンパイルしてみる。

Reactはwebpackを使ってbundleしてやるので、

import React from 'react';

を一番上に付け加える。

Step 3: 最小のUI stateを特定する

  • インタラクティブにするために、Reactではstateを使ってデータモデルへ変更を伝える。
  • DRYに沿って作る。最小のmutable stateを特定する。(富豪的に考える。キャッシュはひとまず考えない)
    1. 親か流れてくるpropsはstateにはしない
    2. 時間で変化しないものはstateにしない
    3. 他のpropsやstateから計算できるものはstateにしない

次のデータ一覧のうち*印をつけたものが今回のstate

Step 4: stateがどこに伝播するのか決める

ProductTableはSearchBarのフィルターを使う。ここでまとめるようなコンポーネントはFilterableProductTableである。よってフィルターテキストやチェックボックスのstateはFilterableProductTableに持たせる。子コンポーネントにはpropsを使って渡す。

Step 5: 子から親へのデータフローの追加

  • SearchBarからFilterableProductTableへ変更を伝えるコードを追加する。
  • Reactの方法では2wayバインディングよりもコード量は増えるが、明示的で分かりやすい。
  • inputタグのvalueは常に親からのpropsを反映している。
  • inputタグのvalueに変更があれば、SearchBarのhandleChange()が呼ばれ、その中で、prop.onUserInputというコールバックが呼ばれている。(propsにはコールバックを指定することもできる。)
  • このコールバックは親のFilterableProductTableのstateを変更するものである。 f:id:ishn:20150831145951p:plain

Flux(Redux)は次回。

自分の集中力を上げた話

TL;DR

私はこれでネットサーフィン(死語か?)を1日6時間から1日10分に圧縮できました。

前置き

研究室のグループワーク等では、各員のモチベーションに差がない状態のほうが珍しい。そこで、やる気が出ないひとに向かって、「なぜやる気がでないんだ!」と叱咤して、果たしてプロジェクトは成功するんだろうか。グループワークでは、メンバーを思うがままにするのが目的ではなく、プロジェクトの成功が目的なのである。ストレス無く人の行動を促す方法があったらいいね。

と思ってググったら、日本でもそういうのを提唱してる人が居た。

www.hitachi-solutions.co.jp

(ステマじゃないよ)


行動分析学という心理学の分野がルーツらしい。(J-ABA 日本行動分析学会(The Japanese Association for Behavior Analysis) ) 。これを、仕事のフレームワークまで落とし込んで、行動科学マネジメントという名前にしたようだ。

単純に言うと

  • 人は、行動するきっかけがあり、過程が楽で、その結果利益があるのが分かっていれば、やる
  • 人は、行動するきっかけが少なく、過程が大変で、その結果ストレスがあるのが分かっていれば、やらない

という仮定が前提にあって、つまりきっかけ、過程、結果を細かく分析して制御してみようという話らしい。

良さそう。ということで、まずは自分に適用してみた。つまり、「私はこれをやるぞ!絶対にやるぞ!」という自己啓発ドリブンを辞めて、ならざるを得ないような仕組みに変えるのだ。これで、1日の作業の密度が格段に上がったので、この記事に覚書しておく。

分析

私は集中力が無い。全然無い。1日4時間以上ネットサーフィンしてるかもしれない。やばい。

毎日大学に行っているし、研究室のデスクの作業環境に不満は無いから、日々の作業のきっかけと過程はラクチンなはず。しかし、コンピュータを使う作業な以上、ネットサーフィンのきっかけと過程も同様にラクチンなはず。しかも、研究と違って、ネットサーフィンは即効性のある楽しさに溢れている(Youtubeでよく、Epic Cat Compilationとか2時間くらい見てた)。

行動科学ではこんな感じで対処するらしい

  • 不足行動: やりたいけどできてないやつ
    • きっかけを増やす
    • 過程を簡単にする
    • 利益を増やす
  • 過剰行動: やらなくていいのに過剰にやってるやつ
    • きっかけを減らす
    • 過程を難しくする
    • 利益を減らす

今回は、過剰行動であるネットサーフィンをやめるために以下のことを行った。

  • 行動の分析
    • 条件: PCがあるorスマホを見てる
    • 1. 席に着く <- ココと
    • 2. Chromeをひらく
    • 3. Ctrl-T
    • 4. "facebook" Enter <- コのへんを倒す
    • 5. 更新状況をチェック
    • 5. 猫動画貼ってる人がいるのでクリック
    • 6. Youtubeへ飛ぶ
    • 7. 関連動画を見る
  • きっかけを減らす:
  • 過程を難しくする

f:id:ishn:20150517152051p:plain

やった結果

大成功です。酷い時は半日くらい、Facebookのタイムラインとおもしろ記事を行ったり来たりしてたのが、今や10分で"仕 事 中 じ ゃ な い で す か ?"(意訳)という煽りページにリダイレクトされる。

Scrum for Trelloで作業時間の管理してるんだけど、かなり正確になった。監督者が居なくても、1日9時間の空きに対して、ちゃんと9時間見積もり分の作業を差し込めるようになった。すごい!

次は、グループワークにも応用したい。