【個人開発】これまでになかった席替えアプリ「席替えメーカー」を作りました

# はじめに

こんにちは、[@krpk1900_dev](https://twitter.com/krpk1900_dev)と申します。
以前教師として勤めていた経験をもとに現場で働く教師の業務改善に貢献したいと考え、**「席替えメーカー」**というサービスを開発しました。

https://sekigae.jp/

席替えメーカーは、入力された条件を満たす**席替えの原案を提供する**サービスです。

<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/feceec5d-cc2a-dacd-28b9-2cec69b6d7bf.gif">

席替えメーカーにかけた思いは以下の記事にまとめてあります。

https://note.com/krpk1900/n/n4453088b89dd

# これまでの席替えアプリと違う点

既存の席替えアプリは**ランダムなシャッフル機能だけのものが多く**、例えば以下のような条件を考慮できる席替えアプリは存在しませんでした。

- 目の悪い生徒を最前列に配置したい
- 教室に入りにくい生徒をドアの横に配置したい
- 相性の悪い生徒を離して配置したい
- 勉強が苦手な生徒の横にはサポート好きな生徒を配置したい

# 使い方
### 1. 全体の形と班の形を入力する
まず、**全体の座席の形を選択**します。班の形も変えることができます。
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/8993194f-3c68-ed1d-c555-332a1074a643.gif">
### 2. 今の座席に生徒名を入力する
次に、**現在の座席に生徒名を入力**していきます。**クリックで生徒の性別を切り替えること**ができます。
<img width="330px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/660c137f-164c-5289-a432-156010ec5bc2.gif">
### 3. 条件を入力する
**席替えの際に検討する条件を入力**していきます。現在入力できる条件は以下の6通りです。

- 前後で指定する
    - 最前列
    - 前2列
    - 後ろ2列
    - 最後列
- 特定の座席に固定する
- 生徒同士を近づける
- 生徒同士を離す
- 今の座席から全員移動させる
- 男女の座席を固定する
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/8219c191-f08a-8852-2171-5a94f92f6c81.gif">

### 4. 席替えボタンを押す
**席替えボタンを押して座席を移動**させます。良さそうな座席の配置が見つかるまで、席替えは何度でもできます。サイドバーを開いて条件を修正することもできます。
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/090fab44-4b7b-a6f0-d636-dacbfd436641.gif">
### 5. ドラッグで最終調整する
**ドラッグで座席を入れ換える**ことができるので、良さそうな座席の配置を元にして最終調整を行います。
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/fed6f7cf-1cf7-4044-ea94-64130b8ccef1.gif">
# 使用技術
- Vue.js 2.6.12
- Vuetify 2.4
- sortable.js 1.13.0
- intro.js 3.3.1
- Netlify

# 力を入れたポイント
### 1. すべての条件を満たす座席の配置を求めるアルゴリズム
- AさんとBさんを離す
- CさんとDさんを近づける

上記の条件を満たすだけなら、以下のように単純に順番通りメソッドを呼び出す処理で問題ありません。

```javascript
makeFar(A, B);
makeNear(C, D);
```
しかし、

- AさんとBさんを離す
- AさんとCさんを離す
- BさんとCさんを近づける

上記のような絡み合った条件を満たす場合は、単純に順番通りにメソッドを呼び出すような処理では実現できません。

```javascript
makeFar(A, B);
makeFar(A, C);
makeNear(B, C);
```
Aさんから離してBさんを配置し、Aさんから離してCさんを配置するときに、その時点でCさんがBさんに近づいているかを確認する必要があります。

実際にこのサービスを利用するときは、**入力される条件の多くが互いに絡み合うこと**が想定されました。そのため、複雑に絡み合ったすべての条件を満たすような座席の配置を求めるアルゴリズムの考察には力を入れました。

### 2. ユーザ目線に立ったUI/UX

パソコンやタブレットを使うことに慣れていない人でも直感的に使えるように、現場目線で必要な機能の実装だけでなく**UI/UXの向上**にもこだわりました。

これまで紹介していない例としては、直感的に分かりにくいと思われる部分に**説明を表示したり**、
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/62b1dacc-38c0-7fbf-192c-1bb812c84ef5.gif">
選択すると条件として**矛盾が生じてしまうような生徒名を非アクティブ**にしました。(自前で作成)
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/0fe2a38b-3b86-659f-584e-76dd4ce6aae6.gif">

# 改善したいポイント
### 1. 全体のリファクタリング
Vue.jsを勉強し始めて2日目からこのサービスの開発に着手しました。当時はVue CLIやNuxt.jsの存在を知らず、index.htmlに書き足す形で開発を始めました。そのため、単一ファイルコンポーネントに分割できていないどころかテストフレームワークやLinterも導入できておらず、メンテナンス性が著しく低いコードになってしまっています。

VuetifyがVue3に対応するタイミングで、Nuxt.js+Vue3+Typescriptで現行サービスのリプレイスに挑戦したいと思っています。

### 2. レスポンシブデザイン
現在は一般的なPCの画面サイズにしか対応できていないので、**タブレット**や**スマホ**にも対応させる予定です。
(2021/6/30にタブレットに対応しました！)

### 3. 前回の入力情報をキャッシュに保存
エクセルの複数セルからのコピーアンドペーストに対応できていないため、**サービス利用時に全員の生徒名を毎回入力しないといけない**という点が大きな障壁になっていると感じています。

そこで、席替え後の座席の配置を**キャッシュに保存**しておき、次回の利用時に今の座席に自動で入力することで解決したいと考えています。

### 4. 生徒名の選択肢をダイアログに表示
現在、生徒名を選択するときの選択肢の表示は以下のようになっています。
![現在のセレクトボックス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/e4d1d621-d3b0-56ee-4a28-c62f341c9909.png)
しかし、選択したい1人を40人弱いる生徒の選択肢の中から探すのは大変です。
そこで、生徒名の選択肢の表示を以下のように変更したいと考えています。
![実装したいダイアログ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/c1a75c0e-2af1-06b0-19dc-a0ce1cc5203e.png)
# おわりに
生徒名が流出してしまう不安からサービスを利用してもらえないなど、実際に利用してもらうためにはまだまだ解決すべき課題がたくさんあります。

ただ、自分の目標はこのサービスを作り切ることではなく、**一人でも多くの教師の元にこのサービスを届けて、多忙を極める教師の業務改善に貢献すること**です。やっとスタートラインに立つことができたので、自分にできる限りのことを尽くしたいと思います。

席替えメーカー開発までの記録や改善過程はTwitterに載せているので、気になる方がおられましたら目を通していただけると幸いです。
[@krpk1900_dev](https://twitter.com/krpk1900_dev)
# 追記：サービスのコンセプト
自分がサービスのコンセプトを書いていなかったために、一部の方を勘違いさせてしまいました。追記という形になってしまい大変恐縮なのですが、以下に書かせていただきます。

### 1. 教師が抱える問題
席替えは生徒が楽しみにしているイベントのひとつなので、問題がなければ生徒にくじ引きをさせて座席の配置を決めている教師の方が多いです。

その一方で、人間関係のトラブルが懸念される場合など、**教師がさまざまな条件を考慮して慎重に席の配置を決めなければいけない場面**が存在するのも事実です。その際、ゼロから席の配置を決めていくと、本来時間をかけたい調整ではない部分に時間がかかってしまいます。

### 2. 問題解決のためにとったアプローチ
生徒同士の繊細な人間関係まで考慮する必要があるときは、アプリですべてを自動化するというのはなかなか難しいと思っています。 最後には、生徒一人一人と毎日接している教師自身が、自分の目で見て、自分の頭で考えて調整する必要があると考えています。

しかし、調整する前の**原案はアプリに作らせることができる**と考えました。原案は、人がゼロから作るには時間がかかる一方で、修正されるのが前提となっています。 アプリで複数の原案を高速で作ることで、時間の短縮が可能になります。 それだけではなく、より適する原案を選択し調整を始めることができるので、座席の配置の質を向上させることも可能になると考えました。

### 3. 現場の教師に使ってもらって変更した方針
上記のように、このサービスの開発段階では生徒の前で見せながら使うことを想定しておらず、職員室のパソコンで教師が使うことを想定していました。

しかし、サービスをリリースしてから多くの教師の方にヒアリングさせていただいたところ、私の想像以上に**「条件は入力せずにランダムなシャッフルで生徒に見せながら使いたい」**という声をいただきました。

ヒアリングさせていただいた教師の方々のおかげで、需要が存在するポイントを確認することができました。今後は生徒の前で見せながら使うことも想定しつつサービスを改善していきたいと思います。

# 追記：指摘していただいた改善点
本当にありがたいことに、たくさんのレビューをいただきました。心から感謝しています。
指摘してもらって初めて気付くことができた改善点を以下にまとめます。
### 1. 使い方を分かりやすく伝える(2021/3/18対応済)
LogRocketを使ってユーザがどのように席替えメーカーを利用しているのか分析した結果、**初見で席替えメーカーの使い方が分かるユーザがほとんどいない**という大きな課題に気付くことができました。

また、実際に現役教員の真後ろに立たせてもらい、初見で席替えメーカーを使う様子をモニタリングさせていただきましたが、やはり**機能を使いこなすことができていませんでした。**

そこで、吹き出しのようなダイアログを動的に表示することによって席替えメーカーの使い方をユーザに伝えられるように、最優先で改善したいと思います。

### 2. 条件の削除機能の実装
**条件の削除機能**と、**条件の一斉削除機能**があると良いと指摘していただきました。条件を追加することばかり考えており、取り消し機能の実装をすっかり忘れていました。優先的に対応したいと思います。

### 3. 座席の形を変更しても、入力済みの生徒名がリセットされないように修正
座席の形を変更する際、座席を管理している二次元配列を新しく作り直しているため、時間をかけて入力してもらった生徒名がすべてリセットされてしまっています。こちらも優先的に対応したいと思います。

### 4. xlsxファイルのインポート/エクスポート機能の実装
簡単に調査したところ、エクセルの複数セルからのコピーアンドペースト機能は実装難易度がかなり高そうでした。そこで視点を変えて、xlsxファイルのインポート/エクスポート機能を実装することによって、たくさんの生徒名を入力する手間がかかるという問題を解決できないかと考えています。

# 追記：対応させていただいた改善点
### 1. 配色の変更(2021/3/16対応済)
生徒が席替えのワクワク感を感じるような配色にしてほしいという意見をいただいたため、**全体の配色を明るい色**に変更しました。
![noteのサムネ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/f76b5066-94db-1d21-d1dd-8aa1e0c77da7.png)

### 2. チュートリアルの実装(2021/3/18対応済)
初見だと席替えメーカーの使い方が分かりにくいという意見を多数いただいたので、**チュートリアルを実装**しました。
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/e77a5b46-5973-893e-3190-4107f440ecec.gif">
# 追記：いただいた質問
いただいた質問に対する回答をまとめておきます。質問していただいたすべての方に感謝しています。どうもありがとうございました。
### 1. 名前がだめなら出席番号使えば？
名前の代わりに出席番号を使えばたしかに流出したとしても問題になりませんが、**出力された座席の配置をぱっと見てもイメージできない**というデメリットがあり、最終的にはユーザに選択できる余地を残す判断をしました。

### 2. 入力してもらった生徒名とか条件をDBに保存してユーザごとに管理すれば？
- 使いたいときに何の前処理もなくすぐに使えるようにすることで、アプリに苦手意識を持っている教員の方にもできる限り気軽に使ってもらえるようにしたい
- もし自分が使う側だったら、DBに生徒の個人情報を保存することには抵抗がある

上記の2点を考慮した結果、**バックエンドを設けずログイン機能をつけない方針**を取りました。

### 3. 41人みたいなちょうど長方形にならないときはどうするの？

全体の座席の形を大きめに取り、**使用している座席にのみ生徒名を入力することで対応できます**。
<img width="800px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/4f6c0d77-ecee-0a37-c525-c80b555b5867.gif">
また、一般教室だけでなく**音楽室**や**図工室**などの教室でもサービスを利用できるように、現在は**最大8×8**まで対応しています。
![8*8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693123/d6e89b2b-25b7-aa8c-626e-d60b625ff663.png)

### 4. 有料化しないの？
私立のようなお金のある学校はいろんなサービスを導入している一方で、公立学校にはサービスが導入されることが一切ない現状を自分の肌で体感しました。
今の自分は、**無料で使えるところにこだわって一人でも多くの教員の方に貢献したい**という気持ちが強く、**有料化するつもりはありません**。

# 追記：謝辞
この記事を皆様が読んでくださったことが繋がり、メディアやブログの記事で席替えメーカーを紹介していただきました。

https://internet.watch.impress.co.jp/docs/yajiuma/1312508.html

https://kyoiku.sho.jp/103325/

https://ao-labo.com/sekigae/

https://syutoshi-blog.com/syougakkou-sekigae/

https://www.yacchaesensei.com/entry/2021/05/04/211150

https://nobirub.com/345/

https://hitsuwari-jimpei.com/posts/211201

皆様のおかげで**30,000人**を超える方に席替えメーカーを使っていただくことができ、**たくさんの教師の方から実際に席替えメーカーを活用しているという声をいただきました**。

少しでも自分の夢を形にすることができてとても嬉しく思います。皆様に心から感謝しています。