アンケートに答えたか否かを即時判別できるようなシステムを作った話

# アンケートに答えたか否かを即時判別できるようなシステムを作った話

## はじめに
閲覧どうもです。
[Qiita2020の12日目](https://qiita.com/advent-calendar/2020/typescript)を担当させていただきます。
来年からとうとう社会人になってしまう学生です。
弱弱エンジニアですがメンタル強強なのでどんどん鉞欲しいです。

#### 訂正箇所(更新日)
- getter/setterの説明が逆になっていた。(12/13 16:50)
- Merit, Demeritの表現が不適であった。(12/21 22:32)
    - コメントより、@munieru_jp様ありがとうございます!

## 説明いらん、コード見て理解するからよこせって方向け
[こちらです。](https://github.com/uewolf25/confirm_form)
今回使用するにあたってはGitHubのREADMEに詳しく書いますが、主キーのバリデーションが本学特有のものになるので、
一般向けにも変更する箇所をまとめていきたいと思います。暫しお待ちを。

## 本記事について
主にGsuiteを連携しまくって自動化と可視化の簡易的なシステムを作ったお話をします。(TSがメインではない。)

## どんなシステム?
具体的な内容を記述すると、複数のアンケートに答えなさい。という場面に遭遇したとしましょう。
すると、自分がどのアンケートに答えたかどうか忘れる人が半数いると思われます。
私も大学の部活で８０人管理する立場で活動していましたが、自分が答えたか否かわからなくなる人が多くいました。  
それもそのはず、我が部のアンケートは自分のスケジュール等を確認しないといけなかったので、即時回答できるものではなかったのです。
また、問い合わせも多かったので、そのやりとりを無くすために作ったシステムになります。  
長くなりましたが、今回はその仕組みのと言語としてTypeScriptを使用したので、便利な点を紹介していきたいと思います。

### 仕組み
Gsuiteを使用するので、アンケートはGoogleFormを使用します。
自分で確認できるようにGoogleSpreadSheetを使用します。

![caconfirm_architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/cf60cd50-5ecd-0fe0-fdc5-f185dd2247fa.png)

#### 使用技術
- language  
  - TypeScript  
- tool  
  - webpack  
  - clasp:2.3.0  
  - node:v14.15.1  
  - npm:6.14.8  

![caconfirm_architecture2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/de01d5f5-09d0-7402-eabd-af17daf7d9ca.png)
図が不適だったので更新(12/12 22:33)



### 必要なもの
用意するものは３つです。
1. アンケートのタイトル名
シートにつける名前を決めてください。  
2. 任意のアンケート  
判別するための主キーを用意して下さい。(学籍番号もしくは氏名でもいいです。)
3. 予め名簿を載せるスプレッドシート  
氏名・学籍番号などを載せておきます。
4. 回答したかを閲覧するスプレッドシート  
このシートをユーザが確認するので、閲覧権限でURLを配布します。

流れとしては、1でキーを取得して、2のシートで合致した人の表示を3で緑色のセルにします。
上記４種類をスクリプトのプロパティとしてセットします。

#### 1.フォームのタイトル
今回タイトル名は「event1」とでもしておきましょうか。  

#### 2.アンケート
次にアンケートです。  
![form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/be4ddb9e-fc80-8b96-b89d-ecbb7a108b79.png)
 

#### 3.予めデータを載せておく用のスプレッドシート
![advance_sheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/c1b123e3-c3be-1a67-577e-de3ed4230089.png)


#### 4.閲覧用のスプレッドシート
![everyone1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/b8ef6326-2e75-f2d8-5ea2-3ee404f506ee.png)


### こんな感じ
![animated.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/7044aca8-724a-db01-2d4a-06d1247a23d3.gif)


「3.予め書いておいた名簿」から情報を「4.一般向けのスプレッドシートに記述。」

![animated2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483644/8e6c8034-f522-8b1b-fa27-5fc82d2b604b.gif)


アンケートに答えるとその人のセルに色と記号を与える。  
ここでは「56」を判別材料としています。  
また、シートもしっかり「event1」で生えていることがわかる。

こんな感じで上記プロパティ４つをセットするだけであとはフォーム送信時に自動で更新を行ってくれるので、手を加える必要がないんです。（たまにエラー吐きよる）
色付きですぐにわかるよねってやつ。

### Pros
- サーバレスで簡単に開発。
- シートのURLを踏むだけでアンケに答えたか確認ができる。
- 色や記号で「回答した」「回答していない」がすぐにわかる。
- アンケート毎にシートも自動で分けられ、正しく反映される。
- フォーム送信時に自動的に更新が行われる。(編集権限付きURLをセットするだけでおk。)
- シートに記述される内容は表示されない(機密化)
- 答えていない人がいたら周りの人がお互いに声の掛け合いで答えてくれる。

### Cons
- サーバレスなのでサーバの勉強にはならん。
- URL知ってたら誰でもアクセスできちゃう。

### ToDoリスト
全員が見れるスプレッドシートしか用意していないので、かつ、URLさえ知っていればアクセスできちゃうので(閲覧のみ)個人用のページを作ろうと思って放置したまま。(誰か作って〜 :D)というってもサーバレスでWebページも作れちゃうのでそこまで手間はかからんが。
あとはテスト・設定ファイルの編集。


## TypeScriptを使ってみて
### 使う経緯
1. 型が欲しかったので、静的型付けのTSを採用。
1. 自分の使い慣れたエディタを使いたかった。

### 感想等
1. エラーがはっきりしている。  
今回はかなり特殊な使い方をしていて、元々GAS使わなければならないのですが、
独特のエディタであったり、エラー内容がわかりづらかったりと不便な点が多かったので、[clasp](https://github.com/google/clasp#deploy)とwebpackという技術を用いてトランスパイルしたのちファイルを一つに統合しました。  

1. 環境構築が楽。  

1. オブジェクト指向でかける。    
型が使えるというだけで、自分がコードを書いているうちにどういう型が返ってくるのか、がすぐにわかるのでやはり静的型付けは良きです。 :)   (とか言いながらany型を使ってしまうと意味がないんですがね笑)
ちょうどオブジェクト指向のデザインパターンも勉強している最中だったので、意識してかけてちょうどよかったです。(今見てみると改善箇所が多くありますが^^;)
今回抽象クラスを作ってみようかと思ったのですが、トランスパイル時にうまく変換されないためか、
実行ができませんでした。(まあ元々型がないJS君に変換するには相当の代用物がいるはず。。。)  

1. getter/setterが書きやすい。  

``` Property.ts
...(略)
/**
  * - Get Form URL from 'GF_URL' property .
  * @returns this._form : Google form URL
  */
public get getForm(): string {
  return this._form;
}
...
```

上記のようにTSにはgetter/setterの修飾子があるので、コードの可読性が個人的には上がります。(Pythonは確か@シンボルでいい感じにかけた気がする。)
もちろんgetterは返り値を、setterは引数を必ず必要とします。ないとエラーが出されます。  (12/13 16:50更新)
[Studentクラス](https://github.com/uewolf25/confirm_form/blob/f58cb930d50e152a1730375fb63daecb27f65093/src/Student.ts#L43)でgettter/setter修飾子を使ってないのは`setFlag()`で引数をセットするのが面倒臭かったからだと思います（記憶では）。
trueかfalseをの二択でsetする時はtrueと決まっているので別に引数いらないじゃん、って感じでわざと抜いてます。ん〜もっといい書き方ありそう。。。  


# まとめ
- アンケートに答えたかどうか忘れてしまった時、シートを見れば一発でわかるよ。  
ざっくりいうとこんなシステムです。   
フィードバックくれた部活の方々には感謝を。  
<br>
今回は簡易的なシステムを作った話とその使用した技術に関しての個人的な感想を書きました。  
最近は全然メンテできてないですが、時間がある時にでもリファクタリングをしていきたいです。
また、Unionなど面白い要素が入ってて個人的には使いやすかったので皆さんも使ってみてはどうでしょうか？  
私もまだまだなのでアドカレのTS枠も拝見させてもらって勉強します〜。(遅くてごめんなさーい！)  
以上！良い１２月を！！！

# 参考
- [gas-clasp-stater](https://github.com/howdy39/gas-clasp-starter)
- [Google Apps Script をローカル環境で快適に開発するためのテンプレートを作りました](https://qiita.com/howdy39/items/0e799a9bfc1d3bccf6e5)
- [node installがうまくいかなかった対処法](https://github.com/nodejs/node-gyp/blob/master/macOS_Catalina.md#The-acid-test)
- [Google認証がうまくいかない時](https://www.acrovision.jp/service/gas/?p=252)
- [プロパティのセットがうまくできない](https://auto-worker.com/blog/?p=1708)