Goalist Developers Blog

Azureの顔認識APIで感情分析!社内の幸福ランキングを作成する

こんにちは、開発部のイイオです。

機械学習、はやりですね。
ゴーリスト社内でもモデル作成に勤しむ青年の姿が見受けられます。
でもパンピ〜の我々は、機械学習でいったいどんなことできるのか、手っ取り早くその果実を味わいたいですよね。

というわけで
Microsoft Azure が提供している顔認識の分類器を使って、会社の人々の幸福度を測定してみました。

今回計測にかけたのは、採用のために人事がやってるブログのこちらの記事です

blog.goalist.co.jp

上記ブログの写真から人間の顔を検出し、以下の8つの感情に分類します。
anger, contempt, disgust, fear, happiness, neutral, sadness, surprise

手順

1. APIキーを取得

API利用のためのキーを取得します、無料のゲストでOK
1分あたり20回のリクエストが可能です。

azure.microsoft.com

2. プログラムを書く

こんなかんじで、、

Python界に生まれて3日目くらいの人間が書いているので、お作法的にnot goodかもしれません
間違ってる部分あったらこっそり教えてください〜

やってることは

  1. 人事ブログ記事をクロール
  2. スクレイプして画像のURLを入手
  3. Face API に投げる
  4. 顔認識された座標で画像を切り取ってローカル保存
  5. 感情分析の結果をCSV出力

プログラム全体はこちら

3. 実行する

画像フォルダに切り出されたみんなの顔が増えていくのは正直わろうた

結果

同率1位

喜び以外の感情が全く検出されない、
フルハピネスなお祭り野郎はこいつらだ!!!

f:id:y-iio:20181115165702j:plain HRogの顔、営業部を統括する男

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115165103j:plain お調子者の美女っていうのも良いですね

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115181623j:plain インドからの刺客

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115165800j:plain 石油王ではない ※参照

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115181642j:plain こう見えてムッッッッキムキの兄さん

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115181709j:plain ちからつよそう

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115181731j:plain 天パ

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0


f:id:y-iio:20181115181821j:plain ドラえもんかな?

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0



2位〜 ハピネス度92.8〜99.9%のみなさん

f:id:y-iio:20181115182643j:plain こんなに破顔しているのに0.1%の悲しみが検出される"闇"

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.999 0.0 0.001 0.0


f:id:y-iio:20181115182932j:plain ちょっと笑顔が足りなかったですかね

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.995 0.0 0.005 0.0


f:id:y-iio:20181115183101j:plain 見切れがたたったか

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.973 0.011 0.021 0.0


f:id:y-iio:20181115183436j:plain 曇りなき(まなこ)です

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.953 0.046 0.0 0.0


f:id:y-iio:20181115183706j:plain 知的な美女というのも良い

anger contempt disgust fear happiness neutral sadness surprise
0.001 0.0 0.0 0.0 0.928 0.071 0.0 0.0



喜び以外の感情と判定された中間層!

f:id:y-iio:20181115184120j:plain 心の中では全く笑っていないのかもしれません

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.004 0.0 0.0 0.202 0.794 0.0 0.0


f:id:y-iio:20181115184238j:plain あまり感情が表に出ない文系エンジニア

anger contempt disgust fear happiness neutral sadness surprise
0.001 0.001 0.0 0.0 0.122 0.866 0.011 0.0


f:id:y-iio:20181115184724j:plain 真面目な話をしているので…

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.049 0.938 0.012 0.0


f:id:y-iio:20181115184854j:plain 菩薩

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.002 0.981 0.016 0.0


f:id:y-iio:20181115185112j:plain 下向きの顔だとハピネス度が下がるのかもしれません

anger contempt disgust fear happiness neutral sadness surprise
0.001 0.0 0.0 0.0 0.0 0.833 0.166 0.0



最下位の中からPick UP!

f:id:y-iio:20181115182105j:plain 99.9%の無と0.1%の悲しみをたたえたフェイス

anger contempt disgust fear happiness neutral sadness surprise
0.0 0.0 0.0 0.0 0.0 0.999 0.001 0.0



感想

Pythonで何かしら動く、ふざけた楽しいプログラムを作りたいという気持ちで気軽に始めましたが
スクレイプ、画像処理、外部API利用、ファイル出力と色々試せて有意義でした。有意義でした!
決して、決して仕事の時間中に遊んでいたわけではないのですよ!

Gitをふんわり図解するシリーズ③ コンフリクト解決編

この前社内でGitのハンズオンを開催したので、コンフリクト解決に関する部分をまとめました。
基本的なコマンドは使えるけど、手元でコンフリクト解決したことないぜよな初心者向け。
基本用語解説編基本コマンド編とも合わせてドウゾ

何なの

まずはイメ〜ジの話なのですけど

f:id:y-iio:20181113184736p:plain
ロボを作っているラインがあるとします。
ある作業ブランチでは「左腕を武器に換装する」変更を、
ある作業ブランチでは「全身のカラーリングを赤にする」変更をしています。

f:id:y-iio:20181113184754p:plain
「左腕を武器に換装する」変更を先にマージし、後からカラー変更をあてようとすると
コンフリクトが発生します。

左腕を赤く塗ろうと思ってたのになんか知らない武器付いてるよ!
親方〜〜〜これ塗っちゃって良いんすか確認お願いします!!!

的な状況です。

いつもならGit職人くんが特に確認なくうまいことマージしてくれるのですが
同じ箇所を変更するような場合は判断できないので人間の親方の出番です。

f:id:y-iio:20181113184832p:plain
武器はやっぱツヤ消しの黒色がいい…
カラー変更は上腕まででよし…

親方こだわりのディテールを職人に教えてあげる

f:id:y-iio:20181113184914p:plain
完成!つよそうですね

やってみよう

実際に手を動かすとこんなかんじです

こんなテキストファイルconf.txt があったとする

ロボを作るよ

branch1ではこう変更

ロボを作るよ
左腕を武器に換装する

branch2ではこう変更

ロボを作るよ
機体を赤く塗る

branch1の変更をマージ後、branch2をマージしようとすると…コンフリクト発生!

$ git merge branch2
Auto-merging conf.txt
CONFLICT (content): Merge conflict in conf.txt
Automatic merge failed; fix conflicts and then commit the result.

とりあえずは状況の確認をする
conf.txtがboth modifiedですって

$ git status
On branch confex
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   conf.txt

no changes added to commit (use "git add" and/or "git commit -a")

conf.txtの中身を見てみると
職人からの確認部分に「<<<<<<< HEAD」とか書き足されている

ロボを作るよ
<<<<<<< HEAD
左腕を武器に換装する
=======
機体を赤く塗る
>>>>>>> branch2

「=======」を境界にどっち側使うの〜と聞かれてるのでどっちもだ!と教えてあげる

ロボを作るよ
<<<<<<< HEAD ←消す
左腕を武器に換装する
======= ←消す
機体を赤く塗る
>>>>>>> branch2 ←消す

ロボを作るよ
左腕を武器に換装する
機体を赤く塗る

変更を保存してコミット

$ git add conf.txt
$ git commit -m "fix: conflict"

解決!

気軽にコンフリクト解決していきましょう٩( ‘ω’ )و

こんなのもあります

developers.goalist.co.jp

developers.goalist.co.jp

Gitをふんわり図解するシリーズ② 基本コマンド編

最近社内でGitの勉強会を開催したので、 図解部分をまとめました。
いつもなんとなくコマンド使ってるけど実際のとこあんまりイメージ湧かないぜ〜みたいな時に使えるTipsです。
基本用語解説編と合わせてドウゾ〜

git clone

f:id:y-iio:20181030193011g:plain
共有されてる保管場所をコピってきて、同じ形した自分のための保管場所を手元のPC内に作る

git init

f:id:y-iio:20181030194014g:plain
手元で製造工場を作ってから共有する場合もある

git log

f:id:y-iio:20181030193429p:plain
いつ誰がどんな意図でこの変更をしたのかを確認します

git add

f:id:y-iio:20181030193604p:plain
自分の変更部分を包みます

git commit

f:id:y-iio:20181030194142p:plain
包んだ変更をまとめてセーブ!

git push

f:id:y-iio:20181030194424p:plain
リモートリポジトリにブランチを作成
または、ブランチに変更内容を反映

git fetch

…の前に

f:id:y-iio:20181030195010p:plain ローカルリポジトリには2種類のブランチがあります

f:id:y-iio:20181030195043p:plain

・リモート追跡ブランチ
リモートリポジトリのブランチを参照するだけのブランチ
手元でいじれない
git branch -aでremotes/origin/xxxx とかなってるやつ

・ローカル作業ブランチ
手元での作業用
いつも使ってるやつ

f:id:y-iio:20181030195224g:plain
リモートリポジトリの上流ブランチを参照して、リモート追跡ブランチを更新すること
それがフェッチです

git merge

ブランチ上の変更を統合します

f:id:y-iio:20181030195514p:plain
作業ブランチ同士で、、とか

f:id:y-iio:20181030195438p:plain
リモート追跡ブランチから作業ブランチに、、とか
リモートリポジトリでの変更を作業ブランチにも反映させたい、そんなときはこの形です

git pull

f:id:y-iio:20181030200034p:plain
フェッチしたリモート追跡ブランチの変更をローカル作業ブランチにマージする、のをいっぺんにやるのがプルです。

pullで何も引数に指定しないと、上流ブランチが指定されてる作業ブランチ全てに対し
リモートリポジトリでの変更が反映されてしまうので、
けっこう予想外のマージが起こってあたふたしちゃったりします。

フェッチとマージができればプルを使う必要が全くないです、
プルして変にハマっちゃうくらいなら使わなくていいんじゃないのかな〜と思います

技術の図解もの

こんなのも書いてます

developers.goalist.co.jp

developers.goalist.co.jp

次回はコンフリクト解決についてまとめます

Gitをふんわり図解するシリーズ① 基本用語とチーム開発の流れ

最近社内でGitの勉強会を開催したので、
Git初学者向けの基本用語解説部分をまとめました。

リポジトリ

f:id:y-iio:20181029162159p:plain
リポジトリはプロジェクトに必要な複数のファイルを保持します。
また、これまでのすべての変更履歴を保持します。

f:id:y-iio:20181029162239p:plain
リポジトリはそれぞれブランチを持ってます。

ブランチ

f:id:y-iio:20181030192154g:plain
並行作業で開発するためにブランチが使われます。
やること別に作業ラインが分かれてたほうが、他の人の邪魔にならないし不具合の原因も見つけやすいですよね。

f:id:y-iio:20181029162343p:plain
ブランチとコミットオブジェクトはこんな感じで図にされることが多いです。
この玉みたいなやつをコミットってことにしますね。
セーブポイントが積み重なっているんだなあというよなイメージでお願いします。

チーム開発の基本的な流れ

f:id:y-iio:20181029185013g:plain
手元で開発する

みんなに共有する

みんなが最新の同じソースを使える

HAPPY

技術の図解もの

こんなのも書いてます

developers.goalist.co.jp

developers.goalist.co.jp

次回は基本コマンド編をお送りします。要チェックやで、です。

ラズパイで無駄なもの作るよシリーズ① 初期設定編

こんにちは、開発部のイイオです。

会社ではWebアプリを企画したり作ったり運用したりしています。
ユーザーが料金以上の価値を得られるような、そんな商品を目指して、、

しかしタイトルにもあるように、無駄なもの、そう無駄なものが作りたいのです私は
誰の役にも立たない、ただただ自分が楽しいだけの無駄なものが

そもそもコスパとか生産性とか、ビジネスで重要っぽく語られる諸々、
突き詰めたら今すぐ死ぬのが一番効率良い(個人の感想です)のに折り合いつけられるものかよ〜〜

そんなわけで休みの日は無駄なものを作って健康さを取り戻したいと思います。

ラズベリーパイというちっちゃなコンピュータ基盤を使って、なにがしかを作ろう
ワイワイ!

www.raspberrypi.org

とりあえずは初期設定を行います。

必要なもの

  • ラズパイ本体
  • ネット繋がってるPC
  • microSD 8GB以上
  • 有線キーボード
  • 有線マウス
  • 5VのマイクロUSB接続の電源
  • ディスプレイ

OSのインストール

1. microSDにOSデータを落とす

お手持ちのPCでNOOBSをダウンロード
データが重いので10分以上かかりました

Raspberry Pi Downloads - Software for the Raspberry Pi

f:id:y-iio:20181029160838p:plain

zipを展開したら、中身をゴッソリmicroSDに移動

2. ラズパイの接続

microSDをラズパイにさす

有線キーボードと有線マウスをラズパイにさす

ディスプレイのHDMIをラズパイにさす

電源をさす

f:id:y-iio:20181029155527j:plain

とりあえずさしまくる、電源が最後ならなんでもいい

すると

f:id:y-iio:20181029155647j:plain
デロロ....
CPUが1このやつは左上のアイコンも1こだそうです

3. OSのインストール

f:id:y-iio:20181029155743j:plain
インストールするOSの選択
Raspbianをチェックして、左上のインストールボタンを押す

f:id:y-iio:20181029155824j:plain
インストール中の様子

microSDけちってしょぼいやつ買ったので、20分近くかかりました

4. できあがり

f:id:y-iio:20181029160014j:plain
パスは初期設定のままでいいかな

user: pi
pass: raspberry

f:id:y-iio:20181029160115j:plain
日本語フォントも最初から入ってるみたい、そこはかとなくかわいらしいフォントです

f:id:y-iio:20181029160150j:plain
linuxのターミナルが使えます
ネットに繋いでないから時計は狂っとる

5. うわ〜〜〜

Scratchというプログラミングで猫を動かして遊べるやつ
もともと教育用コンテンツなのでこういうの入ってるんだね

f:id:y-iio:20181029160537g:plain
楽しい

次回はLEDをつないでチカらせます!

機械学習のモデルを理解しましょう!

歴史

機械学習がもう30年ほど存在してきたが、最近のプロセシング力に至って、使える場面が物凄く増えてきました。昔も、今も数学的なアルゴリズム(Naive Bayesなど)を使い予測などを行ってますが、最近の復活の原因はほとんど、「Deep Learning」というやり方のおかげです。これは最新のプロセシング技術に頼って、今までにない複雑なモデルの作成ができます。

Deep learningの力

さて、このモデルとは何?美人さん? f:id:c-pattamada:20181025143637j:plain

すみませんでした。もちろん、違いませんね。画像を使いたかっただけです、恨まないでください。


例えば、こういうデータがあります。

f:id:c-pattamada:20181025143712p:plain

なんか、高校の数学授業を思い出す。この赤い点のを通して線を書きましょう。例えば「y = 2x + 4」 。これが「モデル」と言います。

そして、このデータをよく描いているモデルだとも言えます。

f:id:c-pattamada:20181025143731p:plain

この場合は一般線形モデル、[y= 2x + 4」を使いました(辞書がそういうから。英語ではlinear modelです)。

一直線が十分なので、機械学習なんかより高校生にでも聞けば良いかと思います。

ではもうちょっと複雑な例を見ましょう。そして、似たようなモデルを使ってみましょう。

f:id:c-pattamada:20181025143746p:plain

こちらは明らかに使えません。 そこで、2乗や3乗などの y = 0.2x4-5x2+10x+5 (これも「モデル」と言います)みたいな数式でできるでしょう。(数式はちょっと適当に選びました)

f:id:c-pattamada:20181025143757p:plain

実際にはどうなる?

この場合はたった一つの変数、「x」、を使って、「y」を予測してます。つまり、もし家賃の値段が「y」と、それを計算する時に「家の広さ」という「x」のみを見ているようなものです。現実の世界には、家賃の値段が実際には - 駅からの近さ、(「z」) - 部屋の数 (「w」) - 何年前に構築された (「v」) 見たいな変数にも影響されているでしょう。 その場合、4つの変数でn乗まで計算しようとすると、結構複雑になります。y = 2(x2)zw3 - 3 (v/z) + ..... 見たいに、もう読めないぐらい。 このような複雑なモデルの作成にはdeep learningが非常に強いです。

そうですよ。モデルの心って、複雑ですよ。

(写真はこちらから) Free stock photos · Pexels

Angular6とPlayFramework2.6でWebアプリの雛形制作(リクエスト送受信)

こんにちは。
増田です。

この間Angular6とPlayFramework2.6での環境構築の資料を作成する機会に巡り合ったので、
せっかくなのでそれを流用し、その2つを使ったリクエストの送受信までの手順を記事として残しておこうかと思います。
目標としては、画面上のボタンを押すと画面にサーバー用プログラムからのレスポンスが表示されるだけの簡単なものです。
あくまでWebアプリの雛形。

Macを買ったばかりという想定で、何もないところから全部入れていきます。

環境

ハードウェア:Mac
フロントエンド:Angular6
バックエンド:PlayFramework2.6

必要なものの準備

いろいろと必要になってきますので、それらを一つ一つ入れていきます。
すでに入っているものはさっくり飛ばしていただければ。

必要なもの

  • Java8以上 / JDK
  • Xcode
  • Command Line Tools for Xcode
  • Homebrew
  • sbt
  • Nodebrew
  • Node.js / npm
  • Angular CLI
  • IDE

それぞれが何のためのものなのか、僕はよく知らないので割愛します。
調べていただければたくさん出てくると思います。

Java8以上

初っ端から他の方のサイトを参考するのもどうかと思うのですが、
僕が書く必要もなさそうなので。ぺい。
macOS に Oracle Java 8 (JDK) をインストールする手順

最終的に、ターミナルにjava -versionと入力して、
f:id:s-masuda:20181017101022p:plain
というように返ってきたら大丈夫です。
java version "1.8.〜"というのが重要です。

Xcode

App Storeで「Xcode」と検索すると出てきます。 f:id:s-masuda:20181017101057p:plain
ダウンロードして、一度開いて、ライセンスに同意しておきましょう。

Command Line Tools for Xcode

またしても他の方のサイトを参考に...。ぺいっ。
MacにHomebrewをインストールする

けど、一応書いておきます。
ターミナルにxcode-select --installと入力して、
f:id:s-masuda:20181017101132p:plain
が出てきたら、インストールボタンを押してください。
ライセンスの使用許諾にも同意しておきましょう。

Homebrew

上のものと同じサイトが参考になります。
ターミナルに/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"と入力すればおしまいです。
あとはダウンロードされるのをしばし待ちましょう。

もしダメだった場合、例えば
f:id:s-masuda:20181017101157p:plain
というようなものが返ってきた場合には、
Homebrewにアクセスして
f:id:s-masuda:20181017101218p:plain
の白い文字の部分をターミナルに入力してください。

そうして上手くいくと、途中でEnterキーの入力とパスワードを
f:id:s-masuda:20181017101315p:plain
f:id:s-masuda:20181017101311p:plain
こんな感じで求められるので、入力しましょう。
パスワードは自分のアカウントのログインパスワードです。

インストールが終わったらターミナルにbrew -vと入力してみてください。
f:id:s-masuda:20181017101430p:plain
というような感じで返ってきたら大丈夫です。

sbt

参考に、というか公式サイトをぺいっ。
Mac への sbt のインストール

ターミナルにbrew install sbt@1と入力しましょう。
インストールが終わったらsbtと入力してみてください。
すると色々ダウンロードが終わったあとで対話モード(左側に矢印が出ている状態)になると思います。
その状態でexitと入力すると対話モードを終えれます。
終えましょう。

Nodebrew

とりあえず参考にさせていただいたサイトをぺいっ。
買いたてのMacにNode.jsとnpmをインストール

ターミナルにbrew install nodebrewと入力しましょう。

インストールが終わったら、ターミナルにnodebrew -vと入力してみてください。
f:id:s-masuda:20181017101741p:plain
一番上にこんな感じで返ってきたら大丈夫です。
その下に長々と出てくる分は無視しています。

Node.js / npm

上と同じサイトを参考にしています。

ターミナルにnodebrew install-binary latestと入力しましょう。
もしこんな感じのエラー(download failed)
f:id:s-masuda:20181017101859p:plain
が出た場合には、ある場所にディレクトリ(フォルダ)を一つ作る必要があります。
なので、その場合には、ターミナルにmkdir -p ~/.nodebrew/srcと入力しましょう。
これで大丈夫です。
そのあとにもう一度nodebrew install-binary latestと入力してみてください。
インストールされるはずなので。
f:id:s-masuda:20181017101919p:plain

ターミナルにnodebrew listと入力して、
f:id:s-masuda:20181017101951p:plain
こんな感じで返って来れば大丈夫です。

インストール直後は current: none となっていると思います。
currentには使用するバージョンが来るのですが、そこがnoneになっているので、
それを指定します。
ターミナルにnodebrew use v10.10.0などと入力しましょう。
ただし、v以下はnodebrew listと入力した時に表示された値にしてください。
v10.10.0ではないかもしれません。

次にnodeコマンドへのパスを.bash_profileに保存します。
「nodeコマンド」とか「パス」とか「.bash_profile」とか分からないかもしれませんが、
僕もよく分かってないのできっと大丈夫です(あかん
ターミナルに

echo 'export PATH=$PATH:/Users/****/.nodebrew/current/bin' >> ~/.bash_profile  

と入力しましょう。ただし、上記のコマンドの****の部分には自身のユーザー名を入力してください。
ターミナルの設定がデフォルトなら、ターミナルを開いたときに

(PCの名前):~ (ユーザー名)$  

という形で左側に表示されていると思いますので、そのユーザー名の部分を****のところに入力してください。

コマンドを打つ形ではなく、ホームディレクトリに.bash_profileというファイルを作成し、
そこに直接書き込むという形でも大丈夫です。
そちらの方が分かりやすい気もします。

.bash_profileへの記述まで終われば、最後それを反映するためにsource ~/.bash_profileと入力しましょう。
参考のページには~/.bashrcを利用していますが、使用しなくても大丈夫だったので気にしないことにします。

確認として、ターミナルにnode -vと入力してみてください。
f:id:s-masuda:20181017102043p:plain
こんな感じで返って来れば大丈夫です。
Node.jsがインストールされたついでに、npmというのもインストールされているはずなので、
ターミナルにnpm -vと入力してみてください。
f:id:s-masuda:20181017102111p:plain
こんな感じで返ってきたら大丈夫です。

Angular CLI

Angularの環境構築(Angular CLIで構築)が参考になります。
と言っても、することとしてはターミナルにnpm install -g @angular/cliと入力するだけです。

IDE

これは何か適当に使いましょう。
そもそもIDEがどういうものかについては、
他のたくさんのサイトを参考にしていただければと思います。
ちなみに、僕はWebStorm(Angular用)とEclipse(PlayFramework用)を使っています。

ここまでで必要なものは揃いました。
次はいよいよAngularとPlayFrameworkのプロジェクト作成に入ります。

プロジェクト作成

今回は適当にデスクトップ上に作ってみます。

project
    ┗ frontend
    ┗ backend

というディレクトリ構成にすることにして、projectディレクトリをデスクトップ上に作成します。
二本指でタップして「新規フォルダ」ボタンを押すか、あるいは、
ターミナルで、cd desktopからのmkdir -p projectをしてください。

そして、ターミナルでそのprojectの中に移動しましょう。
今デスクトップ上にいたりいなかったりするかもしれないので、
cd && cd desktop/project/を入力してください。
するとデスクトップ上のprojectディレクトリに移動できたかと思います。

Angularプロジェクト作成

そのままprojectディレクトリ内でng new frontendと入力すると、
frontendという名前のプロジェクトが作成されます。
そこからcd frontendをしてng serve --openとするとたぶんこんなページが表示されます。
f:id:s-masuda:20181017102710p:plain
これでAngularプロジェクトの雛形ができました。

雛形をいじって、ボタンを作るところまでやっておきます。
frontend/src/appにあるapp.component.htmlの中身を全部消して

<div class="center">
  {{content}}
  <button (click)="onClick()">ボタン</button>
</div>

と書いてください。
で、同じ階層のapp.component.cssに

.center {
  display: flex;
  flex-direction: column;
  text-align: center;

  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;

  width: 200px;
  height: 100px;
}

と。別にこんなもの必要ないのですが、趣味です。

最後、app.component.tsの

export class AppComponent {
  title = 'app';
}

を、

export class AppComponent {
  content = 'はじめの第一歩';

  onClick() {
    this.content = 'ボタンが押されました';
  }
}

としましょう。

すると、こんな画面になって、
f:id:s-masuda:20181017102736p:plain
で、真ん中のボタンを押すと、
f:id:s-masuda:20181017102747p:plain
こうなると思います。

一応ざっくりと説明しておきますと、

{{content}}

というのが、app.component.tsのAppComponentクラス内の変数contentを指していて、
その変数の内容を表示するようになっています。
最初、contentには「はじめの第一歩」という文字列が入っているので、それが表示されています。

<button (click)="onClick()">ボタン</button>

ここのonClick()というのが同じようにAppComponentクラス内のメソッドonClick()を指していて、
そのボタンをクリックした時に、そのメソッドが実行されるようになっています。
なのでボタンを押すと、「はじめの第一歩」という表示が「ボタンが押されました」という表示に変わります。

とりあえずボタンを設置できたのでこれでよしとします。
あとでこのonClick()の中身をリクエストを飛ばすように書き換えます。

次はバックエンド!

Playプロジェクト作成

またターミナルに戻って、まずprojectディレクトリにまで行きましょう。
cd && cd desktop/projectとかですかね。

そこで、sbt new playframework/play-java-seed.g8と入力しましょう。
そしたら、プロジェクト名をどうするか聞かれると思いますが、
今回はbackendという名前でやっていきます。
なのでbackendと入力して、Enterキー。
あとorganaizationなど聞かれるかもしれませんが、何も入力せずEnterキーです。

すると、Playプロジェクトの雛形ができると思いますので、
終わったらbackendディレクトリに移動して、sbt runとターミナルに打ってみましょう。
f:id:s-masuda:20181017102828p:plain
というような表示が出たら、ブラウザでlocalhost:9000にアクセスしてみてください。
すると、
f:id:s-masuda:20181017102845p:plain
こんな表示が出ると思います。

雛形はできたので、次はリクエスト用のAPIを作ります。

API作成

以前の記事でAPIを作成する手順も書いたので、さっくり行きます。

以前と同じようにしてroutesファイルに

GET     /api/get                    controllers.ApiController.get

と書いて、 backend/app/controllersにApiControllerクラスを作成し、

public class ApiController extends Controller{

    public Result get() {
        String res = "レスポンスです!";
        return ok(Json.toJson(res));
    }

}

と書きましょう。必要なものはimportしつつ。

このままリクエストを送ると、
f:id:s-masuda:20181017102922p:plain
のようなエラーが出るかもしれないので、
application.confに

play.filters.enabled += "play.filters.cors.CORSFilter"

と書いておきましょう。
なぜかエラーを回避できます(おい

とりあえずバックを動かしておきましょう。
backendディレクトリに移動した状態でsbt runです。

これでAPIは作成できたので、次はフロントからリクエストを飛ばします。

リクエスト送信

Angularプロジェクトの方で最初に書いた

onClick() {
    this.content = 'ボタンが押されました';
}

を編集します。

まず、Httpリクエストを飛ばせるようにするために、
app.module.tsに2行書き加えます。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http'; // <-------コレ!

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule, // <-------コレ!
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

「コレ!」って書いてある部分です。

そして、app.component.tsにも2行

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http'; //  <-------コレ!

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  content = 'はじめの第一歩';

  constructor(private http: HttpClient) {} // <-------コレ!

  onClick() {
    this.content = 'ボタンが押されました';
  }
}

書き加えましょう。

これでリクエストを飛ばす用意が整ったので、onClick()メソッド内でhttpリクエストを飛ばしてみましょう。

onClick() {
  this.http.get('http://localhost:9000/api/get').subscribe(
    (res: string) => {
      this.content = res;
    }
  );
}

とするだけです。
this.httpというのがconstructorの部分で取ってきたHttpClientにあたり、
getでGETメソッドを利用し、引数にリクエスト先を書き込みます。
それをsubscribeすることで、レスポンスを受け取ることができます。

あとは、作ったボタンを押してみましょう。
すると、
f:id:s-masuda:20181017103009p:plain

f:id:s-masuda:20181017103013p:plain
わお!

めでたしめでたし。

あとはAPIやらあれこ作ってみたり、
フロントで画面を作り込んでみたりすると、
Webアプリが作れるわけですね。すごい。

次はこのアプリ(とは言えない何か)をデータベース(MySQL)と連携させるお話を書く予定でいます。
そのうち。
いつかきっと。