初めてハッカソンに参加してみた話

{メリークリスマス, ハッピーホリデー}！
[限界開発鯖 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/approvers)の25日目，ラスト[^1]の記事です．
今年ももうすぐ終わりますね...僕はこの記事を書いていたら，いつの間にかクリスマスを迎えてしまったみたいです．

さて，この記事では僕が人生初めて参加したハッカソンに対して思ったことを色々書きたいと思います．
※ちょっと長いです＞＜

![thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/9662d8c6-23fc-0fba-ed37-a0c240535289.png)




# そもそもハッカソンとは
> _《hack（ハック）＋marathon（マラソン）からの造語》ソフトウエア開発者が、一定期間集中的にプログラムの開発やサービスの考案などの共同作業を行い、その技能やアイデアを競う催し。_
[Weblio辞書](https://www.weblio.jp/content/%E3%83%8F%E3%83%83%E3%82%AB%E3%82%BD%E3%83%B3)より

一定期間内にモノを作り，発表し，アイデア力や完成度，実用性などを競うイベントです．

# どんなハッカソンに出たの？
[Web×IoT メイカーズチャレンジ 2020-21 in 信州](https://webiotmakers.github.io/2020/)に参加しました．

## 応募資格
>- 16才以上の方で学生、社会人問わず学習意欲のある方
- プログラミングや電子工作に興味のある方 (講習やハッカソンでは、JavaScript を使います。
初学者の方は事前にJavaScriptの予習をお願いします。)
- 原則として 11/7-8 の講習会、12/5-6 のハッカソンの計 4 日間にご参加いただける方
- ノートPC (Bluetooth接続が可能なPC) を持参できる方

[Connpassページより](https://webiotmakers.connpass.com/event/189801/)

## 日程
- 【Day 1】11/07 (土）ハンズオン講習会
- 【Day 2】11/08 (日）ハンズオン講習会＆アイデアワークショップ
- 11/9 〜 12/4 ここで各チーム開発
- その内12/02 〜 12/04 高専チームテスト
- 【Day 3】12/05 (土）ハッカソン
- 【Day 4】12/06 (日）ハッカソン
- 12/07 工学実験実習 レポート[^16]提出

うーん，もうヤバそうな日程

# 【Day 1】11/07 (土）ハンズオン講習会
IoT の基礎と電波やワイヤレス通信についての基礎知識講座やmicro:bitの基礎的な動作を学びます．

## micro:bitとは
教育向けのマイコンボードです．25個(？)のLEDを搭載していたり，デフォルトでBluetooth通信ができたりと，色々すぐれものです．
[こんな見た目してる](https://www.google.com/search?q=micro:bit&tbm=isch)

## CHIRIMEN with micro:bitとは
[CHIRIMEN with micro:bit](https://tutorial.chirimen.org/microbit/)はmicro:bitの機能を，Web Bluetooth APIを用いて**__ブラウザ上で__インタラクティブに操作するライブラリ**です．コンパイルとかも必要ありません．USBすら挿さなくていいあたりがなんか令和な開発だなあって思いました．
以下は，Bluetoothでmicro:bitと接続し，GPIOポート0を出力ポートとして設定するコードのサンプルです．

```mbit.js
let gpioPort0;

const connect = async() => {
	// chirimen with micro:bitの初期化
	microBitBle = await microBitBleFactory.connect();
	console.log("micro:bitとのBLE接続が完了しました");

	// GPIOポート0の初期化
	const gpioAccess = await microBitBle.requestGPIOAccess();
	const mbGpioPorts = gpioAccess.ports;
	gpioPort0 = mbGpioPorts.get(0);
	await gpioPort0.export("out"); //port0 out
}
```

めちゃくちゃ簡単ですね！
特にmicro:bitとの接続が`microBitBleFactory.connect();`だけでできるのがとても魅力的でした．
今回のハッカソンではこのライブラリを使うことが条件でした(**重要**)．

# 【Day 2】11/08 (日）ハンズオン講習会＆アイデアワークショップ
ここらへんでハッカソンのアイデアを投げ合う & メンバー自己紹介をします．
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【信州】ハンズオン講習会2日目！こんな進捗も報告してくれています！スバラシイ！！🎉<a href="https://twitter.com/hashtag/WebIoTmakers?src=hash&amp;ref_src=twsrc%5Etfw">#WebIoTmakers</a> <a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a> <a href="https://twitter.com/hashtag/CHIRIMEN?src=hash&amp;ref_src=twsrc%5Etfw">#CHIRIMEN</a> <a href="https://t.co/VZgSzvk6at">https://t.co/VZgSzvk6at</a></p>&mdash; Web×IoT メイカーズチャレンジ (@WebIoTmakers) <a href="https://twitter.com/WebIoTmakers/status/1325309509753958400?ref_src=twsrc%5Etfw">November 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これは僕の進捗を紹介してくださった運営様のツイート．

## チームJanbi結成:tada:
メンバーの頭文字を取ってこの名前になりました．GitHub: [@Team-Janbi](https://github.com/Team-Janbi)
<dl>

  <dt>JPig</dt>
  <dd>高専出身．めちゃくちゃ頭がいい．最近JSを始めたらしい[^3]．
<dl>
<dt>得意そうな言語[^4]</dt>
<dd>C, LaTeX</dd>
<dt>ポートフォリオ</dt>
<dd>https://jpig-main.github.io/mypage-1/index.html</dd>
<dt>Twitter</dt>
<dd>[@JPig_Main](https://twitter.com/JPig_Main)</dd>
<dt>GitHub</dt>
<dd>[@JPig-Main](https://github.com/JPig-Main)</dd>
</dl>
</dd>

  <dt>PLAODAS(A氏)</dt>
  <dd>社会人の方．Web系のお仕事経験者．仕様伝えたら3秒後ぐらいに実装されてる[^5]．早すぎ．
<dl>
<dt>得意そうな言語[^4]</dt>
<dd>PHP</dd>
<dt>GitHub</dt>
<dd>[@plaodas](https://github.com/plaodas)</dd>
</dl>
</dd>

  <dt>Noiri</dt>
  <dd>大学出身の方．Myキーボード持ち歩いてた．絶対Pythonなんでも知ってる[^6]．
<dl>
<dt>得意そうな言語[^4]</dt>
<dd>Python</dd>
<dt>GitHub</dt>
<dd>[@Noiri](https://github.com/Noiri)</dd>
</dl>
</dd>

  <dt>Bony_Chops</dt>
  <dd>俺．高専出身．トークン開示大魔王[^8]．なぜかリーダーになってしまいました．
<dl>
<dt>得意そうな言語[^7]</dt>
<dd>JavaScript，PHP(最近触ってない)</dd>
<dt>ポートフォリオ</dt>
<dd>[https://bonychops.com](https://bonychops.com)</dd>
<dt>Twitter</dt>
<dd>[@BonyChops](https://twitter.com/BonyChops)</dd>
<dt>GitHub</dt>
<dd>[@BonyChops](https://github.com/BonyChops)</dd>
<dt>YouTube</dt>
<dd>[Bony_Chops](https://youtube.com/c/Bony_Chops)</dd>
</dl>
</dd>

  <dt>Token-05(I氏)</dt>
  <dd>高専出身．めちゃくちゃ頭がいい．JPigの影響でJS始めてた．
<dl>
<dt>得意そうな言語[^4]</dt>
<dd>C, LaTeX</dd>
<dt>Twitter</dt>
<dd>[@081keiji](https://twitter.com/081keiji)</dd>
<dt>GitHub</dt>
<dd>[@Token-05](https://github.com/Token-05)</dd>
</dl>
</dd>

</dl>

## アイデアワークショップ
何をつくるかを決めます．今回のテーマは「With コロナ」でした．Google Spread Sheetに，テーマに合ったシチュエーションと解決策を羅列していき，「独創性・有用性」「実現可能性」の観点で評価することで今回の作品を決めます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/d864bb83-b857-5661-12ca-176cab5d73db.png)
上のやつでひ・み・つって書いてあるやつが今回採用されたアイデアです．このSheetは他のグループも見れ，アイデアをパクられたくなかったので秘密にしちゃいました．

## 完成したアイデア
アイデアワークショップをした結果，「**人が密集したら，除菌スプレーを散布しに来てくれるロボット**」を制作することに決まりました！:tada::tada:
でもどうやって実現するのでしょう．ここでこの日の活動は終わりです．

# 11/9 Discord鯖設立 & 大まかな仕様決定
こんな感じになりました．(字が汚くてごめんなさい)
<dl>
    <dt>Sデバイス</dt>
    <dd>据え置きのセンサー．これで人の人数を測定する．</dd>
    <dt>Cデバイス</dt>
    <dd>クライアント(グローバル上の鯖と区別するためにこの名前にしたが，実際はローカルの鯖)．Sデバイスから受け取った人数を元にMデバイスへ司令を出す．</dd>
    <dt>Mデバイス</dt>
    <dd>Cデバイスから受け取った司令を実行する．つまり除菌スプレーを運んで散布するロボット．</dd>
    <dt>ぐろーばるな鯖</dt>
    <dd>Web AppやLINE botなどで送られてきたリクエスト(部屋の人数が知りたい，Mのスプレー散布を開始してほしいなど)を処理し，Cデバイスへ送る．</dd>
</dd>
</dl>
「スマホから部屋の人数把握・スプレー散布のタスクを実行とかできたらいいよね」


![IMG_20201109_233505.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/b2965398-7948-37ac-790c-0e79f907e739.jpeg)
![IMG_20201109_232322_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/acf4f402-80a0-35f1-c1e3-cd24ca639079.jpeg)
![IMG_20201109_232638_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/87caa097-76d8-bf94-b366-247a7360a1f6.jpeg)
![IMG_20201109_233234.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/126dcb17-1939-b78b-aa96-75440eb68255.jpeg)

# 11/10 グローバル鯖できた
Bony「グローバル用の鯖どこにしようかな[^9]」
A氏「こことかおすすめですよ借りておきました」

# 11/11 初めてのDiscord会議 / 役割分担が決定
こうなりました

|役割|メンバー|仕様|
|---|-------|---|
|S  |Noiri  |Python, OpenCV|
|C  |PLAODAS(A氏)|PHP|
|M(主にハード)|JPig, Token-05|micro:bit, Raspberry Pi
|M(主にソフト)|Bony_Chops|{Node.js, Python}
|ぐろーばるな鯖| Bony_Chops|{Node.js, PHP}
{}は当時不定だったもの

# 11/16 Noiriさん(Sデバイス)の進捗
こんな感じの仕様にしてくださいました．天才．神．(図も作ってくれた)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/27cc9efc-0b73-af08-1433-90973277772a.png)

ラズパイで動かすことを想定して，重いタイプと軽いタイプも作ってくださいました．[こんな感じの図](https://www.pinterest.jp/pin/792703971891761827/)で解析してみると，以下のようになったそうです(Macbook Proで検証)．

|タイプ|所要時間|精度|
|-----|------|---|
|重いタイプ|15秒程度|6人検出(100%)|
|軽いタイプ|ほぼ一瞬|4人検出(66.67%)|

結果，ラズパイに載せるため精度を犠牲に軽いタイプを載せることになりました[^10]．

# 11/17 Mデバイスの挙動を検討
今回のゴールは「**人が密集したら，除菌スプレーを散布しに来てくれるロボット**」ですが，この「**来てくれるロボット**」をどうやって実現するかを検討しました．
高専チームで話し合った結果，「事前に部屋までのルートを記録し，Cからの司令があったとき(人が集まった時)にそれを再現する」という形で実現することにしました[^11]．

![image0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/f1533168-be2a-aaba-162a-a314a6c73978.jpeg)

# 11/18 〜 11/20 Mデバイスの材料決定 / 購入
言い忘れてましたが，**材料費は2万円まで支給が出ます**．その範囲内に収まるように調整しました[^12]．

(画像は予算の一部)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/f885def4-d0ad-9257-2a42-e08424b690f4.png)

# 11/21 プロジェクトの名前決まってなかった
ハッとしました．画像はfirebaseプロジェクトを建てるとき．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/a9a5f76f-9c1d-5b62-adb4-0cec511d06b8.png)
そのときに俺が適当に名付けた「**COVIDiffuser**」が正式名称になってしまいました．

#11/26 Mデバイスプロトタイプ完成
[Mデバイスプロトタイプ 動いている様子(動画)](https://youtu.be/_dQUi6HUyPw)
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/732ca687-cf2b-1e71-dc04-9a6f17d24afc.png)](https://youtu.be/_dQUi6HUyPw)

いい感じに動いていますね

# 12/01 API鯖完成 / 日程見直し
PLAODAS(A氏)さんにAPI鯖を作っていただきました．あれ？Bony_Chopsの担当だったはずじゃ...[^13]
さらに，ココらへんで日程を見直し，ゴールを見直しました．
唯一残る課題は，認証のフローが一切なく**誰でもリクエストを投げられるところ**．

- 各デバイスのタイプ(SデバイスのA1とかA2,Bとか)をなくし，1種類だけの実装を目指す(S, M, Cのみ)
- Cデバイスをローカルではなく，グローバルにする(MデバイスをRas Piが乗ってるM-Bタイプのみにする→Wi-Fiが使えるから)

# 12/02 〜 12/04 高専テスト
死ねるよね:point_up:[^14]．

## 前日の進捗チェック
こんな感じです．

|役割|メンバー|情強|
|---|-------|---|
|S  |Noiri  |Ras Piで実際に運用済み，CへのPOSTテストも完了し，**ほぼ完成**|
|C(グローバル鯖)  |PLAODAS(A氏)|JWT認証導入済み，必要なエンドポイントも揃い，**ほぼ完成**|
|M(主にハード)|JPig, Token-05|動作確認済み，部品も揃い，**ほぼ完成**
|M(主にソフト)|Bony_Chops|...

# 【Day 3】12/05 (土）ハッカソン
テスト明けのハッカソン．
本当はここまででほとんど完成していて当日はゆっくり...

## トラブル発生
できません．知ってた[^18]．

### Sデバイス - Noiriさん
**昨日まで起動したRaspberry Piがお亡くなりになりました**．
最初はWi-Fiに接続できなく，メンターさんにLANケーブルを借りてなんとか運用しようとしたのですが，今度は依存関係のOpenCVが壊れ，動かせなくなってしまった模様．
前日まで動いたのに，ここへ来て急に壊れるのはどうして...[^19]

### Mデバイス(ハード) - JPig, Token-05
ほとんどデバイスが完成し，スプレーを散布するときに使用するサーボモータを取り付けたときに発覚．**サーボモータのトルク(回す力)が全然足りない！！！**．しかもそのせいか，**なんか痙攣してる！！！！(ｳｨﾝｳｨﾝｳｨﾝｳｨﾝｳｨﾝｳｨﾝ)**
動画撮ればよかったですね．まあその時は焦りまくっててそれどころじゃなかったんですが．

### Mデバイス(ソフト) - Bony_Chops
大変です！！！！**何も進捗が生えていません！！！！！！！！！！！！！**
ということで，今からMデバイス(ソフト)の具体的な仕様を決めます[^20]．
おそすぎますね．はい．大変申し訳無いです．

#### 仕様どうしよう...
最初はこんな感じにしました．以下はMデバイスでルートを記録するフロー．
![first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/b7000fb3-b0be-7d77-d3dc-3397aa54722b.png)

以下メンターに突っ込まれたところ

- メンター「1~2のローカルIP渡す下り，本当にいる？」  
俺「ゆ，ユーザーがシームレスにMデバイスに接続できるようにしたくて...」  
メンター「発想自体はいいと思うけど，とりあえず動かせる段階に持ってくために，まずはIP直うちでいいんじゃないかな．**時間ないんだし**」  
俺「はい」
- メンター「3〜5，具体的にはどういう流れ？」  
俺「まず，リモコンが操作されたときにページ上のJSがexpress上のAPIを叩いて，expressからRas Pi上で起動しているChromium[^22]へ**_どうにかして_**データを渡して，ChromiumからCHIRIMENライブラリでmicro:bitへ...」  
メンター「ユーザーに操作されるんだったら，この方法だと多分遅延すごいよ．それにこれRas Piからexpressでホストして，それをmicro:bitに渡すんでしょ？なんか冗長な気がする」  
俺「はい」
- メンター「ホストするリモコンページはどうやって作るの？」  
俺「とりあえず，Reactで作って...」  
メンター「さっきから思ったけど，Bony君Nodeに執着しすぎじゃない？生のHTMLとJSに書いたほうが早いと思うよ．**時間ないんだし**」  
俺「はい」

**_う ううぅ..._**[^21]
#### 改善案

改善案を考えました．以下は登録してから部屋へ行くまでのフロー．
![second.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/5c5edf1b-cedd-7b92-9aea-35d37f9783d7.png)[^24][^25]

これなら，

- ローカルIPを打たせる下り大変そう  
→そもそもBluetoothのペアリングだけだからわかりやすいし，実装が大変じゃない！
- リモコン→express→Chromium→micro:bit→Mデバイスは流石に冗長 / 遅延やばい  
→ スマホから直接micro:bitを操作するから，遅延も(そんなに[^23])ない！
- Node.jsに執着しすぎ  
→俺が諦めて生のHTMLを書いてGitHub Pagesでホストすれば解決！

#### いざ実装

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/eb8f28aa-973d-2ab1-4624-a116f20c6014.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/31707deb-be99-aecb-8065-eca6ac0a4c46.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/10ba5e37-e337-f6cb-e6f8-c9fae3728f69.png)
[Materializecss](https://materializecss.com/)を使っていい感じに仕上げます．動作もいいかんじです．あとはCデバイスへPOSTして...ん？

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ここで会ったが百年目ッッッッッッッッ！！！！！！！！！！！！！！！！！<br>文化祭以来だな貴様ああああああああああ！！！！！！！！！！！！！！！！！！！！！！！！！！！<a href="https://twitter.com/hashtag/WebIoTmakers?src=hash&amp;ref_src=twsrc%5Etfw">#WebIoTmakers</a> <a href="https://t.co/F0IMt4gkvg">pic.twitter.com/F0IMt4gkvg</a></p>&mdash; Bony_Chops (@BonyChops) <a href="https://twitter.com/BonyChops/status/1335067773009940481?ref_src=twsrc%5Etfw">December 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/8426beab-ca4b-5fbd-76b7-20ded2d84782.png)


### Cデバイス(グローバル鯖) - PLAODASさん
**CORSくん「やあ！」**

#### CORSくんとは

>_セキュリティ上の理由から、ブラウザーは、**スクリプトによって開始されるオリジン間 HTTP リクエストを制限**しています。例えば、 XMLHttpRequestや Fetch API は同一オリジンポリシーsame-origin policyに従います。つまり、これらの API を使用するウェブアプリケーションは、そのアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことができ、それ以外のオリジンの場合は**正しい CORS ヘッダーを含んでいることが必要**です。_
[オリジン間リソース共有 (CORS) - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)より

セキュリティ上の理由から，ブラウザ上から任意のAPIを叩くときは，**サーバー側が**「(このドメイン[^26]でホストしているページからであれば)いいですよ」という意思表示が必要です．イメージだとこんな感じ．

![cors-success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/648904b4-2987-9316-6aea-f950347fb4a9.png)

実際の挙動は，
1. ブラウザ側から，リクエストする予定のURIと同じエンドポイントへOPTIONSメソッドでリクエストする
2. サーバー側から，Headerに`Access-Control-Allow-Origin`が含まれるレスポンスを返す(ここに許可するドメイン[^26]を載せます)
3. リクエストをすることが許可され，実際のリクエストがされる

という感じです．ただし，サーバー側に設定されていなければ...

![cors-failed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/9745b941-5609-ff19-222d-7d8715740079.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601799/8426beab-ca4b-5fbd-76b7-20ded2d84782.png)

という風に，リクエスト自体が送れなくなってしまいます．

ということでPLAODASさんに`Access-Control-Allow-Origin`をHeaderにつけていただきましょう．

#### お願いします...
俺「ということで，修正をお願いしたいです...」  
PLAODAS「うーん，ライブラリ[^27]使ってるからそんなとこ修正できるかわからないなあ...しかも，今のAPIの仕様上，認可するために`Authorize`ヘッダが必要じゃん？ないと403返っちゃうけどいいの？[^31]」  
俺「あー...じゃあ，OPTIONSメソッドのときだけ200(204)を返すとかは無理ですか？？」  
PLAODAS「...`技術的には可能です`[^28]」  
俺「**_Merge!?!?!?!?!_**[^29]」

困りました[^30]...
ここでこの日の活動は終わりです．_本当に大丈夫か...？_

## 迫る魔(レポート)の手(期日)
おまけに明後日はレポート提出期限．ちょっとでも進めておかなければ無事高専機構に○されてしまうかもしれません．どうしよう...
俺「ま，明日の夜頑張ればいいか！」

**_レポートは捨てました:innocent::innocent::innocent::innocent::innocent:_**
とにかく進捗を生やします．

## 夜中にPLAODASさんからDiscordが
PLAODAS「やっておきましたよ:anger:[^32]」
俺「**うおおおおおおおおおおおおおおおおおおお！！！！！！ありがとうございますありがとうございますありがとうございますありがとうござ**」
もうここまでやってもらったら進捗を生やさざるを得ません．がんばります．

### 結果
一旦寝て，朝早く起きて進捗を生やしました．
とりあえずルートを記録し，サーバーにPOSTするところまでできました！**成功しました！**

# 【Day 4】12/06 (日）ハッカソン
そして迎える発表当日．泣いても笑ってもこれがラスト[^1]です．とりあえず発表は15:00，集合する9:00からお昼を含めてあと6時間ほどあります．がんばりましょう．


## 現状の問題点

|役割|メンバー|問題点|改善策|解決済|
|---|-------|---|---|---|
|S  |Noiri  |Ras Piが死亡|MacProで運用|✅|
|C(グローバル鯖)  |PLAODAS(A氏)|ブラウザからのリクエストがCORSによってブロックされる|適切なヘッダを設定する|✅|
|M(主にハード)|JPig, Token-05|サーボモータのトルク不足によりスプレー散布できない|スプレーを運送するロボットへ変更|✅|
|M(主にソフト)|Bony_Chops|完成していない|完成させる|

**俺だけですね！！！！がんばりますね！！！！！**

## なんとか完成
な，なんとか完成しました:tada::tada::tada::tada:
## 発表の準備
一つのグループに付き5分の発表があります．Zoomを使い，全会場へ放映されます．万が一のために，リハーサルを兼ねて動画を撮影しておきましょう．

### トラブル発生
なんと作成したMデバイスに搭載しているモバイルバッテリーが**一斉に故障し始めました！！！！**
_どうして...  う ううぅ..._
とりあえず，うまく動くデバイスを確認し，何度か撮影していいテイクを選びます．

## 結局最終的な仕様はどうなったのか
こうなりました

|役割|メンバー|仕様|
|---|-------|---|
|S  |Noiri  |Python, OpenCV|
|C(ぐろーばるな鯖)  |PLAODAS(A氏)|PHP|
|M(主にハード)|JPig, Token-05|micro:bit, Raspberry Pi
|M(主にソフト)|Bony_Chops|HTML, JS
|~~ぐろーばるな鯖~~|~~Bony_Chops~~|Cをぐろーばるな鯖にし，別途用意しない

## 撮影
以外にも，恐れていた事態(デバイスが完全に止まって死ぬとか)はなく，シナリオを事前に考えていたおかげかすんなりとできました．ただ，動画を使うのはあくまで最悪の事態なので，人前で発表できるように練習します．

ちなみに作ったシナリオは以下です．

1. ごあいさつとプロジェクト: COVIDiffuserの紹介
2. 実際にWebアプリを操作(Mデバイスとペアリング，移動，サーバへPUSH)して実演
3. 「これで，この部屋は安全です！人が集まってきたらロボットが駆けつけてきてくれます」
4. Janbiがいきなり集合
5. 適当にメンバーにインタビューして時間つぶし
6. Sデバイスが人を認識，3人以上でMデバイスを動かす設定にしておく
7. Mデバイスがこっちに来る
8. 受け取る
9. JPigにスプレーをかける

これで大体5分ぐらい？

## 発表
発表します．めっちゃ緊張しました．

### 質疑応答タイム
審査員の方の質問に答えます．

#### Q. Sデバイスの人検知の仕組みについて，どのように行っているのか(画面内にいる人数を単に数えているのか，画面内でかつ人の距離が近いかなどを考慮しているのか，カメラ以外にセンサーはあるのかetc...)

**A. 画面内に移った人数をカメラでカウントしています．**
予定では，このSデバイスの他のタイプ(micro:bitのみで実装されたAタイプなど)に，二酸化炭素の濃度を測るセンサを取り入れたり，騒音センサ(もしくはマイク)を用いて，人が話しているかどうかも判定条件にしたかったです．今後これを製品にする場合は，ここの点が改善点とも言えますね．

#### Q. 動くロボットのクオリティが良かった．このようなものづくりは初めてか

**A. はい，なかなか良い経験になりました．**
我々は情報工学科に所属しているため，物理的に何かものをつくることはあんまりないですね．

ごめんなさい，他にもなにか聞かれたような気がしますが，思い出せませんでした...気が向いたら更新しておきます！

## 結果
特別賞をいただけました！！！！！！！
めちゃくちゃ嬉しいです．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Web×IoT メイカーズチャレンジ 2020-21<br>チームJanbiで特別賞いただきました！！！！！！！<br>改めて、このような機会を設けていただき本当にありがとうございました<br>頑張ってくれたチームにも感謝です！<br>あとUI褒められた！！！！！やったぜ！！！！！！！<a href="https://twitter.com/hashtag/WebIoTmakers?src=hash&amp;ref_src=twsrc%5Etfw">#WebIoTmakers</a> <a href="https://t.co/8B2BBdBR87">pic.twitter.com/8B2BBdBR87</a></p>&mdash; Bony_Chops (@BonyChops) <a href="https://twitter.com/BonyChops/status/1335522002262577153?ref_src=twsrc%5Etfw">December 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ツイートにもあるとおり，僕が作ったWebアプリのUIを褒められました[^17]．やったぜ．

## その後
ハッカソンは終わりましたが，まだタスクは残っています．そうです．明日は工学実験実習のレポート提出期限です．死ぬ気でやりましょう．

# 12/07 工学実験実習 レポート[^16]提出
**完徹してしまいました**．というか**_完徹しても終わりませんでした_**．正直たかがレポートとなめていましたが，尋常じゃない報告事項の多さに，Bony君の心は折れてしまいました．素直に再提出評価を待ちましょう[^15]．

# よくありそうな質問
ありそうだと思った質問を書きます．他にあればコメントください．答えられる範囲で答えます．
## Q. チームで出るのと個人で出るのはどっちがおすすめ？
A. 一緒に出れる仲間がいるならダントツでチームで出ることをおすすめします．
もちろん個人で出ることも可能ですが，チーム内のメンバーが全員個人だと**集まるのが大変です**(進捗を1番左右する要素な気がする...)．
僕は今回学校から紹介があり，本当は一人で参加する予定でしたが，勇気をだしてクラスで一緒に出てくれる仲間を募ったところ，あまり話したことがない2人が一緒に出てくれると言ってくれました(今では結構よく話します)．新しい友達を作るいいきっかけにもなるかも？

## Q.本当に初心者でも大丈夫なの？
A. はい，全く問題ありません．事前にJSを少し触っておくようご通達はありましたが，使うドキュメントがとてもわかりやすかったので，多分無知でも行けると思います[^2]．
実際，参加した高専メンバーのうち2人が，ほぼ初めてJSを触ってました(自称)が問題なく操作できていました．

## Q.今回はJS使うハッカソンだったけど，他のスキルは活かせる(活かせた)？
A. はい，というか歓迎されると思います．JSで開発するのはmicro:bitの操作部分だったので，それ以外はどんな言語で書いてもOKみたいです．チームで話し合うときに自分の得意分野がある人はアピールしておいたほうがスムーズに役割分担できます．リーダーになった人は，各個人のスキルを確認する時間を設けるといいと思います．
僕はfirebaseで鯖を建てる予定でしたが，そんな余裕はありませんでしたね(かなしいね)．

## Q.お金はかかった？
A. 昼食代と移動費ぐらいしかかかりませんでした．なんなら，メンバーに社会人の方がいたので，送迎はほとんどその方にお願いしていたので，移動費もかかりませんでした(A氏本当にありがとう)．
使ったmicro:bitは無料，材料は2万円まで支給がでました．

# まとめ
なんだかんだこの1ヶ月，死ぬほど忙しかったのですが，とても楽しかったです．$\tiny{語彙力なくてすみません...}$
正直，こういうイベントには参加したことがなかったので，いろいろと不安はあったのですが，メンバーやメンターさんに支えられてなんとか形に残すことができました．
ただ，ちょっと計画が甘かったですね．もっとやりたいことはいっぱいあったので，もし次機会があれば全てのアイデアを拾うことができるように頑張りたいです．  

長くなりましたが，最後まで読んでくださり，ありがとうございました．


[^1]: Rustではありません
[^2]: とはいえちょっとは触っておきましょうね
[^3]: [ここ](https://jpig-main.github.io/mypage-1/profile.html)に書いてあった
[^4]: 独断と偏見や，本人がそう言っていたような記憶を頼りにしているので，間違っている可能性があります．違ったらこっそり直しておきます．
[^5]: 俺「(運営からRelayServer.jsが提供されているが)せっかくなら鯖自分たちで建てたいですね」A氏「そうですねわかりました建ちました」
[^6]: 今気づいたけど，NoiriさんのGitHub見る限りなんでも知ってそう
[^7]: 本人は得意そうだと思っていますが，得意なんじゃなくて他に書ける言語がないだけだと思います．
[^8]: ？？？「こんにちは Bony_Chops、**安全Jimです！**」
[^9]: 本当はFirebaseでAPI鯖を建てたかったのですが，着手する余裕がなくて結局できませんでした...
[^10]: とある事情で結局重い方を使うことになるのですが...
[^11]: 他にも，「部屋の各地に赤外線と発行する『スポット』(要制作)を設置し，それを目安に部屋まで移動」や，「GPSを搭載し，それを元に移動」，「Webカメラを載せて画像認識によりルートを算出」などの案も上がったのですが，それらの案は別途センサーやデバイスが必要であったり，実装にかなり時間を要するものもあり，「そこばっかり重視してたら企画倒れしそうだよね」ということで一番簡単に実装できそうな方法で落ち着きました．
[^12]: 後に発覚するのですが，**合計が1万3千円しか使っていませんでした**．もっと使えばよかった...
[^13]: 当時高専チームには大量のレポートに加え，12/2(水)にテストも控えていたので，鯖の担当をPLAODASさんにお願いしました..._くやしいです!!!_
[^14]: テストの結果ですが，普段の順位より少し良かったです．_なんで？？？_
[^15]: レポートが返ってきました．報告事項が2つも抜けた~~ゴミカス~~レポートはなんと**再提出を回避しました**．教員曰く「報告事項が2つ抜けてたから減点しちゃった...ごめんね＞＜」とのこと(~~いやごめんねはこっちのセリフなんですが...~~)．
[^16]: 年内で1番重いと言われているレポートです
[^17]: [Materializecss](https://materializecss.com/)使っただけです...
[^18]: 「あれ？家(開発環境)だとうまく言ってたのに会場(本番環境)だとうまくいかない...」は恒例イベントらしいです．
[^19]: 俺「人間と同じで，本番来た瞬間に体調崩してるんですかね」メンター「まあ一番の原因はそれでしょうね」
[^20]: え，それすら決まってなかったの！！？！？！？！？！？！？
[^21]: 実際のメンターさんはここまで厳しい口調では言いません．ご安心ください．
[^22]: わざわざChromiumを起動している理由は，CHIRIMENライブラリは[ここ](#CHIRIMEN with micro:bitとは)にあるように，**ブラウザで使うライブラリ**です．あとで確認した結果，Node.js版はないみたいなので，Chromiumを起動して無理やり動かそうとしています．
[^23]: 完全にないとは言えなかったです．やっぱりちょっとカクつくことがある．
[^24]: 4のフローは，実際にはRas Pi側からGETで数秒に1回クロールしています．
[^25]: 4の後，Ras Pi上ではexpressではなく，Chromium上のJSで直接受け取り，そのままCHIRIMENでデバイスを操作しています．
[^26]: わかりやすくするためにURLと書いてありますが，正しくはOriginです．
[^27]: 名前忘れちゃいました！！分かり次第修正しておきます＞＜
[^28]: > _「できない」とか「やりたくない」ということを、やんわりと伝えたいときに使われる表現のひとつ_ [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word18400.html)より
[^29]: 驚きなどの感情が**混ざり合っている**心情を指す
[^30]: 「そもそも偉そうに言ってますが，Bonyさんがもっと進捗を生やしておけば**ハッカソン本番に気づく**とかいう事態に陥らなかったのでは？」Bony「はいもう本当におっしゃる通りです．申し訳ございません．本当に．」
[^31]: CORSでOPTIONSメソッドが送られる際，レスポンスで403が返ってしまうと**たとえ`Access-Control-Allow-Origin`を適切に設定していてもCORSポリシー違反**になってしまいます．
[^32]: 実際は全然怒っていませんでした．_聖人すぎ..._