リアルタイムでダイスロールを共有するWEBアプリを作ってみた

# 目次
1. 背景
1. TL;DR
1. 使用した技術
1. 手順アウトライン
1. 手順詳細
1. 実用性

# 1. 背景
- 友人たちとTRPGをするようになった。
- セッションはSkype越しにやっており、皆が個別のダイスツールを使っているので、虚偽の報告が可能(しないとは思ってるけど、まぁ、可能)。
- 「ダイスロールの結果を共有できるツールがあったら良いんじゃね?」
- 調べたらいっぱいあるんだけど、なんか妙に多機能で何をすれば良いのかわからなかったり、アカウント作ったりと面倒。
- 「部屋にいる人とだけダイスロールの結果を共有することだけを目的とした、ログインとかいらない、見やすいツールを作ろう」
- ちょうどAngularも勉強してたし、いい機会だと思った。
- Web Socketという技術にも興味があったし、ちょうどよかった

# 2. TL;DR
- github
    - https://github.com/verhichi/trpg-party-dice-roller
- ~~一般公開してるから誰でも使えるよ(now.shに無料デプロイしてるから最初起動するとき遅いかも)~~残念ながらもう起動していません...
    - ~~https://trpg-party-dice-roller.now.sh/~~

ロビー画面の様子
![1543147433168.jpg](https://qiita-image-store.s3.amazonaws.com/0/317253/f13338aa-8eba-0bcc-b4db-5dc2f8568df2.jpeg)

部屋の様子
![1543147738791.jpg](https://qiita-image-store.s3.amazonaws.com/0/317253/17bcbf74-2989-251e-abde-9b10a064d9ae.jpeg)

# 3. 使用した技術
- node.js (v8.10.0)
   - express(v4.16.4) - node.jsの有名なフレームワークのパッケージ
   - socket.io (v2.1.1) - サーバーサイドでweb socketのライブラリを使用するためのパッケージ
   - socket.io-client (v2.1.1) - クライアントサイドでweb socketのライブラリをしようするためのパッケージ
   - @types/socket.io-client (v.1.4.32) - Angularのフレームワーク内でsocket.io-clientを利用するために必要なパッケージ(データ型の情報などがあるんだと思ってる)
- @angular-cli (v1.6.8) - Angularのプロジェクトを始めたり、ビルドしたり、運用したりするためのツール

# 4. 手順アウトライン
1. 調査
    1. Web Socketについて
1. 開発
    1. プロジェクトの土台を作成
    1. 画面の作成
    1. ロジックの作成

# 5. 手順詳細
### 1. 調査
#### 1-1. Web Socketについて
- ちょっとWeb Socketについて調査
- この記事が超簡単に説明してくれてるので、概要を知りたい場合は読むべし。
    - [今さら聞けないWebSocket~WebSocketとは~](https://qiita.com/chihiro/items/9d280704c6eff8603389 "今さら聞けないWebSocket~WebSocketとは~")
- 基本的にわかったことは…
    - イベント名で処理を分ける。
    - emitでイベント名と共にデータを送る。
    - サーバー側もクライアント側も考え方は同じ。


```JavaScript:server.js

// パッケージのインポートなど
const express = require('express');
const app = express();
const http = require('http');
const server = http.Server(app);
const io = require('socket.io')(server);

// クライアントがつながったら
io.on('connection', (socket) => {
  
  // クライアントからのsocket.ioの<eventName>イベントのリクエストを受け取り、渡された[arguments...]を受け取って処理をする
  socket.on('<eventName>', ([arguments...]) => {
     
     /* 何らかの処理 */
     
     // つながっているクライアント全員に<eventName>イベントで<dataToSend>を送る
     io.emit('<eventName>', <dataToSend>);

     // <roomName>にjoinしているクライアント全員に<eventName>イベントで<dataToSend>を送る
     io.to('<roomName>').emit('<eventName>', <dataToSend>);
  });

});
```

### 2. 開発
#### 2-1. プロジェクトの土台を作成

- `@angular-cli`のおかげで簡単に土台を作ることが可能。
- 基本的に以下を覚えていれば問題ないと思う

```:ターミナル
$ ng new <プロジェクト名>　　　　　　　　　 # 新たなAngularプロジェクトのフォルダを作成してくれる
$ ng g component <コンポーネント名>　　　　# コンポーネントのファイルを作ってくれる
$ ng g service <サービス名>　　　　　　　　# サービスのファイルを作ってくれる
```

#### 2-2. 画面の作成
- 画面作成時に意識したのは、レスポンシブデザインとクロスブラウザ対応。
- Bootstrapとか使わずに自分で考えたstyleを使ってみたかった。
- あと、自分はよく暗い部屋でやるので、眩しすぎないように全体的に暗い色合いを使う。
- あとはみやすさ…かな

そんなこんなを考えながらイメージを紙に適当に書いていく…
<details><summary>こんな感じでイメージを少しずつに固めていく(もはやただの落書き)</summary>
![4077.jpg](https://qiita-image-store.s3.amazonaws.com/0/317253/8b4c55c2-d8b0-01a0-86b6-36aba526f536.jpeg)
</details>


- 補足: Internet Explorerに対応させるためにpolyfillを有効化しないといけない。
    - `src/polyfill.ts`ファイルがあるので、コメントを外す。

```TypeScript:src/polyfill.ts

/* (省略) */

// 以下の箇所にコメントがかかってるはずだから全部外す
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

/* (省略) */
```

#### 2-3. ロジックの作成
- 「ロジックの作成」ではかなりざっくりなので、分解すると…
    - ルーティングのロジック
    - 新しい部屋を作るときのロジック
    - 部屋に参加するロジック
    - 部屋の有無を確認するロジック
    - 部屋に誰か入ったときに、それを部屋の人全員に伝えるロジック
    - 部屋に誰か入ったときに、部屋に今現在誰が入っているかを伝えるロジック
    - 部屋に誰かが入ったときにIDを割り振るロジック
    - 部屋に誰かが入ったときにランダムな表示名を割り振るロジック
    - ユーザーが任意に表示名を変更するロジック
    - ダイスを振るロジック
    - ダイスの出目をみんなに伝えるロジック
    - ダイスの出目をログするロジック
    - ログを消去するロジック
    - 誰かが退室したときのロジック

上記をすべて考える必要があった。

# 6. 実用性
個人的な意見だが、実用性は結構あると思う。理由を以下に挙げる…

- 部屋を作って、番号を教えるだけだから誰でも手っ取り早く使えるし、アカウント登録とか必要ない。
- UI/UXを気にして、できるだけシンプルにしたので、見やすく、直感的に使いやすい。
- 機能が少ないので画面がごちゃごちゃしてない。またしても見やすい。
- レスポンシブデザインなのでスマホ・タブレットに対応している。
- 表示名を変えれるようになってるから誰が誰だかちゃんと分かる。

自画自賛もここまでくればキモいけど、まぁまぁの出来だと思っている。
ベースがこれなら機能も追加しやすいだろうし。
ただ、もうちょっとデザインやレイアウトをうまくできたら嬉しかった…
まぁ、これもいい経験ということで…