はじめてのハッカソン　～Yahoo! HackDay 2019～

# はじめに
今回Yahoo! HackDayに会社の同僚と参加しました。

【メンバー】　計２名
私　：趣味でpython3、JavaScriptそれぞれ約１年くらい触った程度、サービス開発未経験
タカ：プログラミング未経験、**ホームページビルダーなら触ったことあるよ！**とのこと

おそらく今回のYahoo! HackDay 2019に参加したチームで、一番伸びしろがあったチームだったと思います。~~開発力なんて皆無なんだよォ！貧弱！貧弱ゥ！~~

はじめてのハッカソン、行く前に不安でどんな感じなのか自分で調べました。
が、開発未経験でいきなりハッカソンに出ようとした方はなかなかおらず
開発のレベル差を感じ、余計に不安になってしまいました。

これからハッカソンに参加しようと思っていて、同じような不安を感じている方の参考になれば幸いです！

##参加経緯
もともとハッカソンには参加してみたいと思いながら、まだ自分の技術じゃなにも出来ないかなと思っていました。

会社で昼飯を食べているときに、ハッカソンの話をタカさんにしたら
HackDay 2019にチーム応募していました。

「当選したよ！メンバーはチケット購入必要らしいからよろしく！」

というメールで決心がつき、参加に至っています。

当初参加メンバーは５名ほど声がかかっていました。

他メンバーが出張予定等で段々と参加できなくなり、結果２人での参加に。
あきらめずに参加した自分をほめてあげることとします。

##イベント時系列
|　時系列 | |
|----------------:|:----|
|12/14   　 12:00|会場到着|
| ～14:00|市場調査|
| ～17:00|企画練り直し、開発スタート|
| ～21:00|Web自動検索|
|12/15　～5:00|OCR機能導入|
|　～6:00|メール送信機能実装|
|　～11:30|Webサーバー構築検討|
|12:00|開発終了|
||発表|

### HackDay前日まで
事前にどのようなプロダクトを作ろうか打ち合わせをしました。
方向性は

- だれもが持っているスマートフォンで気軽に面白いことが出来るようにする
- 被写体が動くのではなく、カメラ側を動かす（スマホをアクションカメラにする）

プログラミングの技術では絶対勝てないので、着想の目新しさでチャレンジしたいというものです。

### 会場到着、市場調査
会場は秋葉原UDX、参加チーム数は78チーム
すでに各チームいろいろな機材を持ち込んだりしていて、周りをみてワクワクしながらソワソワしてました。
会場の通信環境設定だったりをして、人生初めてのハッカソンスタート！HackTime！！

当初想定にあったのは、スマホをゆっくり落下させられるパラシュート的なものが作れないか、といもの。

スマホの加速度センサー Z軸方向数値の安定をトリガーにして、自然落下頂点から
バースト撮影を開始するようという部分にプログラミング要素を組み込もうと考えていました。。

パラシュート機構の部材・参考を探しにドンキ、ヨドバシ、ビックカメラを回ってみて２人は気づきました。
**「アクションカメラの基本機能に投げて撮るってやつあるんだね～、しかも頑張ったら買えちゃう値段じゃん？」**
すでにあるものに面白味を感じなくなり、昼飯を食べながら企画の練り直しをすることが決定しました。

この時すでに14:00、全体の1/12の時間を消費して振り出しに戻りました。

### 企画練り直し
事前に話して出てきたアイディアをもう一度出していきます。
大枠でのキーワード、方向性として、①スマホのカメラ機能を使って、②便利なことがしたい、というのは間違っていないということ。

情報科学とは異なる分野の技術屋さんに刺さるプロダクトを開発したい！ということで
行きついたのがこちら↓
![molcali.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386513/7df53c0c-4000-c8b4-578d-698b5cef0d14.png)

分子量計算機　-MOLecular weight CALIculator-
略して「モルカリ」です。

考えた全体構造は下記の通り↓
![概念図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386513/37d6f022-987e-162f-7197-897da4ab7814.png)

全体像が決まり、
(1) スマホで情報を得たい化学式の写真を撮る
(2) OCRでテキスト情報に変換、Webから自動検索
(3) 得られた情報をスマホにフィードバック

まず３つのセグメントに分けて、順番に開発を進めていきます。

① OCRによるテキスト認識
② Web自動検索
③ メール自動送信

②、③に関しては、pythonで組んだことのある項目だったので
基本的なライブラリの組み合わせでたぶん作れるじゃん！作ろう！と思いました。

①はやったこともなく、どんなものが使えるかも分からなかったので
ひとまず情報収集をしてもらうことにしました。

なので、ひとまずそれぞれの役割分担としては、
私　：②、③部分のコーディング（使用言語：python）
タカ：OCRによる文字認識方法の調査

として開発スタートです。

###Web自動検索
OCRから化学式がtext形式で得られたとして、そこから化学組成、沸点、融点などの情報を取得することが目標です。
今回はpython3のseleniumを使用しました。
Googleで検索しても、html構造が整っていて情報がまとまっているソースに辿りつけなかったため
Wikipediaをスクレイピング対象として、検討していきました。

① OCRで得られたテキスト値を検索窓に入力
② ページ遷移
③ 対象ページからtdタグ要素取得

**・・・the 力技**です。

td要素で得たい化学特性の日本語表現が微妙に違うとうまくヒットしませんでした。
（化学式と組成式 等）
正答率　50%くらい。

たぶん正規表現とかで、検索うまくかければうまくヒットするんだと思います。

```python:webSerch.py
#Web自動検索

import sys
import time
from selenium import webdriver

Metadataset = "hogehoge" #ここにOCRで得たテキスト値を入力

#ChromeをHeadlessモードで起動
options = Options()
options.add_argument('--headless')

#Chromeのパスを指定
#　※Chromedriverが無いとseleniumuは動かない
#　下記パスにあるchromedriver.exeをディレクトリごとコピー
Cpath = r"C:\python\chromedriver\chromedriver.exe"

#Chromeを起動
browser = webdriver.Chrome(Cpath,chrome_options=options)
browser.get('https://ja.wikipedia.org/w/index.php?search=&title=%E7%89%B9%E5%88%A5%3A%E6%A4%9C%E7%B4%A2&go=%E8%A1%A8%E7%A4%BA')

#ページが開くまで待つ
time.sleep(0.5)

#検索入力
time.sleep(0.1)
inputBox = browser.find_element_by_id('ooui-php-1') #htmlで要素idが'ooui-php-1'の要素を取得(検索ボックスの場所取得)
inputBox.send_keys(Metadataset) #取得したInputBoxの場所に変数：Metadatasetの値を入力
link_el = browser.find_element_by_class_name('oo-ui-actionFieldLayout-button')
link_el.click()

#検索ページでの選択
time.sleep(0.1)
link_el = browser.find_elements_by_xpath("//div/div/div/div/ul/li/div/a")
print(link_el[0])
link_el[0].click()

#化学式ページ閲覧
time.sleep(0.5)
title = browser.find_elements_by_css_selector("h1")
value = browser.find_elements_by_tag_name('td')

targetText = []

#リストtargetTextにvalueをリストとして格納
#リストに格納するのは、表示項目を指定するため（'化学式'の次の項目を拾う 等)

for i in value:
    addtext = i.text #i個目の要素をaddtextとする
    targetText.append(addtext)

#物質名
print('物質名：' + title[0].text)

#ほんとは例外処理が必要(インデックスで見つからなかったとき)

#化学式
formulaNmb = targetText.index('化学式')
formula = targetText[formulaNmb + 1]
print('化学式：' + formula)

#モル質量
moler = targetText[formulaNmb + 3] #化学式の下にモル質量が書いてあったので横着した
print('モル質量' + moler)

#沸点
boilingPointNmb = targetText.index('沸点')
boilingPoint = targetText[boilingPointNmb + 1]
print('沸点：' + boilingPoint)

#融点
meltingPointNmb = targetText.index('融点')
meltingPoint = targetText[meltingPointNmb + 1]
print("融点：" + meltingPoint)
```
試しに入力値指定して走らせる

```python:
Metadataset = "NaOH"
```
出力結果

```
物質名：水酸化ナトリウム
化学式：NaOH
モル質量39.992509329 g mol−1
沸点：1388 °C, 1661 K, 2530 °F
融点：318 °C, 591 K, 604 °F
```

例外処理とかも組み込まないといけませんでしたが、他にも課題山積みなので
現状どこまで出来ているか打ち合わせを含め、夕食を食べに行きました。

###OCR機能導入 -Cloud Vision API-
ここから未経験の領域に突入です。

まずは以下の記事を参考に、pythonとTesseract OCRを試してみます。

PythonとTesseract OCRで文字認識
https://qiita.com/henjiganai/items/7a5e871f652b32b41a18

まずは記事通りに画像を読み取らせて、出力したことを確認
これはいけるかもしれない！と思った矢先、写真を取り込むと文字認識しない。

コントラストの問題かな？と思い、前段で２値化変換をかけるようにプログラム改修して再チャレンジ
**がっ・・・駄目っ・・・**

この時点でかなり頭は沸騰しかけていました。

ここでOCR手法についていろいろ調べてもらっていたタカさんが、Cloud Vision APIを使った
OCR文字認識に辿りついていました。

■Google Cloud Visionを使ってみた
https://www.itbook.info/web/2016/11/google-cloud-vision%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F.html

先人たちがいろいろまとめてくれていて非常に助かります。

プログラミングや情報技術に初めて触れるタカさんは
APIキーってなに？JSON？pathを通すってどうやるの？という感じでした。
**１年前の自分もそういう気持ちだったので非常に分かります。**

pythonからAPIリクエストして返ってきたJSONデータを表示するサンプルコードを
タカさんにコピペしてもらい、APIキーなどを書き換えてもらいました。
人生初めてのプログラミングです。

無事に文字認識が成功、文章が返ってきてタカさんは感動していました。
エラーを潰しながらプログラムがちゃんと動いたときは感動しますよね。

さて、返ってきたJSONデータから得たい情報を抜き出します。
最初は返ってきた文章から化学式（アルファベットと数字の羅列）を抜き出すように考えました。
どう頭をひねっても文字長さが決まっていない文字列の抜き出し方が出てきませんでした。

写真の読み取り範囲を限定させるだけの技術はない．．．
いろいろ悩み、２人で現在どの程度出来ていて、残り何をしないといけないか打ち合わせました。
そうだ！**偶然化学式だけ書かれた紙が手元にあることにしよう！**

この時午前３：００、pptで化学式だけ書かれた紙を作成し
コンビニに印刷しに行きます。
外の寒さで眠気も若干緩和されました。

OCRで得たテキストデータを変数格納、Web検索して返すところまでひとまず完成しました。

###メール自動送信
ここは以前組んだことのあるコードそのままに、自分のGmail宛に
web検索で得た情報を格納し、送付するものを作りました。

これでインプットからアウトプットまで一通りの流れが完成しました。

しかし、ここでタカさんの発言に戦慄を覚えます。

タカ「これってスマホ側で写真を撮ったら、自動的にプログラム動かすこととか出来るの？」

私　「Webサーバーとアプリケーションサーバー立てればやれるんじゃないすかねぇ、詳しくは知らないですけど」

タカ「やろうよ！」

**・・・ん？**

###Webメールサーバー構築検討
**地獄の時間がはじまりました。**

ここにきて環境を準備するところからスタートすることに。
ここからのことは正直よく覚えていません。

タカさんにプレゼンの資料準備をお願いし、色々検討しました。

果たしてクライアントサーバー型の方がいいのか
それともスマホ側だけで完結できるアプリを開発できるのか
暗中模索を続け、疲労もピークでうまく頭が回っていませんでした。

結果的には時間内に終わらず、今後の検討課題となりました。

###開発終了
12:00に開発終了、最初のプレゼングループはプレゼン会場に移動となります。

他の参加グループが作ったプロダクトはどれも面白くて素晴らしかったです。
90秒のプレゼンは１発勝負のこわさがありますね。

## 参加した感想
とても苦しくて楽しかった
一番の収穫は自分の限界を引き上げられた感覚が得られたことです。

苦しみながらなにかを生み出すことを、１日に凝縮して楽しむことが出来たと感じます。

まさに**ハック＋マラソン**

終わった直後は早く帰って寝たいと思っていましたが、この記事を書いているとまた来年も挑戦したい気持ちになってきます。

途中特に大事だなと感じたのが、時間を区切ってお互いに考えをすり合わせる時間を作ること
今出来ていることと今からやらなければならないことを都度メンバーの共通認識として持つことが出来たのは大きかったと思います。

つくるってたのしいね