OmniAICreator/Qiita-1.07M huggingface dataset:
開発合宿で firebase + vue.js で日報ツール作った話

この記事は [オプトテクノロジーズアドベントカレンダー(2018)](https://qiita.com/advent-calendar/2018/opt-technologies) 10日目のエントリーです。

# 会社で一泊二日の開発合宿行ってきたよ！

詳しくは以下
[開発合宿2018 in 三浦海岸](https://tech-magazine.opt.ne.jp/entry/2018/12/10/170000)
トップの写真の右端で吠えてるのが私です。

ゆるふわサックリモッチリに書きたかったので、会社の公式magazineではなくQiitaに書く。

# 日報ツールを firebase + vue.js + Vuetify + TypeScript で作った

この見出しでこのエントリで言いたかったことだいたい言った感じ。

### チームメンバーと分担

- わたくし
    - 久しぶりにコード書いたへっぽこCTO
    - 要件考えたり、外部仕様考えたり担当
    - あとは何個か画面作った
- @ovrmrw 
    - 何でもできてすごい。実は既にマネージャー
    - バックエンドのDAO的な一式など担当
    - 夕食の蟹食べ放題が主目的らしい
- M氏
    - フロントエンドすごい担当
    - フロントエンドの環境構築だいたいやってくれた
    - 実装もモリモリしてた
- A氏
    - リーダー
    - 全文検索エンジンなど担当
    - 明け方でも倒れない勢いと若さがすごい

### 構成

- firebase + Cloud Firestore
- vue.js + TypeScript
- Vuetify

### 主要な機能

- 日報や週報が書ける
- 日報や週報を書くタイミングをリマインドする
- 日報や週報に「いいね！」できる
- 日報や週報を書いたら特定の人に周知する
- TODOリストが管理できる
- TODOリストから日報や週報が書ける
- Google Calendar の予定から日報や週報が書ける

など盛りだくさん！

「オプトの日報や週報事情に最適化した日報ツールを作る」をテーマにしました（勝手に）
（オプトではメールベースの日報や週報が~~横行しています~~良く発行されています）

開発合宿で完成したプロトタイプが↓
![スクリーンショット 2018-11-28 1.08.06のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/12369/d13de67c-bd99-c3d9-3fea-2bdb8802b42e.png)

残念ながら、予定していた全ての機能は実装できませんでした…

# 時系列順に

### 開発合宿当日までやったこと

弊社の開発合宿では、業務に影響のない範囲での事前準備が認められています。
あくまで業務に影響のない範囲で、以下の準備をしました。

- 私が、勢いで要件決めて、勢いでデータ設計をやる
- @ovrmrw がDAO層のがっつり基盤部分を作った
- M氏ががっつり環境構築した
- A氏が全文検索のための基盤を作った

### 開発合宿一日目

![iOS の画像のコピー.jpg](https://qiita-image-store.s3.amazonaws.com/0/12369/8f2eefa6-4716-30b3-77ad-24217e86e2d6.jpeg)
寿司食べた

![DSC_1980.JPG](https://qiita-image-store.s3.amazonaws.com/0/12369/8b1463c4-221a-43a4-53b4-40f875f98565.jpeg)
海で遊んだ

![IMG_8597.JPG](https://qiita-image-store.s3.amazonaws.com/0/12369/4ee34b38-193f-42df-2200-c916e9a4c559.jpeg)
夕食ビュッフェと蟹食べ放題食べた

### 開発合宿二日目

![Image from iOS.jpg](https://qiita-image-store.s3.amazonaws.com/0/12369/2196b11a-948a-fb8b-fb4e-e145d94ac4bf.jpeg)
晴れたので海きれい

![IMG_8600.JPG](https://qiita-image-store.s3.amazonaws.com/0/12369/61b9d5e9-04e1-5115-f712-10fc58ed0d81.jpeg)
朝食ビュッフェ食べた

![IMG_8604.JPG](https://qiita-image-store.s3.amazonaws.com/0/12369/cb924145-b9b3-c5f9-0e2f-d8fd45dbca88.jpeg)
カレー食べた

### 食べてばっかりなの？

開発もしましたよ？ たぶん累計16時間くらいは

# 感想や気付いたこと

- 久しぶりにがっつりコード書いて楽しかった
    - そうだね（自問自答）
- vue は vue.js って言うくらいなので JavaScript で開発した方がいいかも
    - [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator) は好みが分かれそう
    - TypeScript だと vue の手軽さや薄さが損なわれる気がする
    - 異論は認める
- Vuetify にはコレ系特有のつらみある
    - サンプルコードから外れようとすると牙を剥く
    - Vuetify 様のお気持ちを理解する必要がある
- firebase 便利
    - すぐにバックエンドが手に入る
    - ただ Cloud Firestore はRDBでないので、それなりに癖がある
    - 大規模サイトもいけるの？
- Visual Studio Code に入信しました
    - VS Code を使ってから肌もスベスベになり、お通じも良く、人としての原罪から救われました
- 来年も開発合宿行きたいね
    - そうだね（自問自答）

現場からは以上です。
【宣伝】Laravel 入門チュートリアル（全11回）を書きました。

![入門Laravelチュートリアル](https://cdn.hypertextcandy.com/posts/laravel-tutorial/eye-catch-a.jpg)

技術ブログに **入門 Laravel チュートリアル（全11回）**を公開しました :grinning: :tada:

せっかく頑張ったのでたくさんの人に見てほしい！
ということで Qiita に宣伝エントリを書きます。

## コンテンツ

Laravel を使った Web アプリケーション開発方法を紹介しています。
ToDo アプリ開発を通して Web 開発のエッセンスを学べるように書いています。

- [入門Laravelチュートリアル (1) イントロダクション](https://www.hypertextcandy.com/laravel-tutorial-introduction/)
- [入門Laravelチュートリアル (2) ToDoアプリケーションの設計](https://www.hypertextcandy.com/laravel-tutorial-todo-app-design/)
- [入門Laravelチュートリアル (3) ToDoアプリのフォルダ一覧表示機能を作る](https://www.hypertextcandy.com/laravel-tutorial-todo-app-list-folders/)
- [入門Laravelチュートリアル (4) ToDoアプリのタスク一覧表示機能を作る](https://www.hypertextcandy.com/laravel-tutorial-todo-app-list-tasks/)
- [入門Laravelチュートリアル (5) ToDoアプリのフォルダ作成機能を作る](https://www.hypertextcandy.com/laravel-tutorial-create-folder/)
- [入門Laravelチュートリアル (6) ToDoアプリのタスク作成機能を作る](https://www.hypertextcandy.com/laravel-tutorial-create-task/)
- [入門Laravelチュートリアル (7) ToDoアプリのタスク編集機能を作る](https://www.hypertextcandy.com/laravel-tutorial-edit-task/)
- [入門Laravelチュートリアル (8) ToDoアプリの認証機能を作る](https://www.hypertextcandy.com/laravel-tutorial-authentication/)
- [入門Laravelチュートリアル (9) ToDoアプリの認証機能を作る パート2](https://www.hypertextcandy.com/laravel-tutorial-authentication-part-2/)
- [入門Laravelチュートリアル (10) エラーハンドリング](https://www.hypertextcandy.com/laravel-tutorial-error-handling/)
- [入門Laravelチュートリアル (11) ToDoアプリをHerokuにデプロイする](https://www.hypertextcandy.com/laravel-tutorial-deploy-to-heroku/)

こんなやつ :point_down: ができます。

![トップページ](https://cdn.hypertextcandy.com/posts/laravel-tutorial/screen_01.png)

コントローラー、モデル、テンプレートなどの軸での体系化はしていません。
ToDoアプリを一画面ずつ作る過程を順を追って解説することで、以下のトピックに一通り触れています。

- URLやテーブルの設計
- ルーティング
- コントローラー
- ミドルウェア
- テンプレート
- モデルとORM
- 単体テスト

たくさんある Laravel の機能のうち本当に初歩の一部しか紹介できていないですが、Web開発初心者の方を念頭に、開発のプロセスや考え方が学び取れるように書きました。

扱っている Laravel のバージョンは現時点で最新の 5.7 です。

## どんな人に読んでほしいか

新人に「とりあえずこれ読んどいて」と渡せるものを目指しました。

なので、新卒エンジニアやWeb開発始めてみたいんだけど、という人を想定しています。

PHPの文法はProgateやドットインストールなどで学んでもらって、「で？何をどう作ればいいの？」という次のステップに読んでほしいです。

## なぜ書いたか

個人的に手を動かして学ぶタイプの学習コンテンツが好きなので書きました。

数年前に私が Laravel を勉強したときに読んだのは「[Laravel 5.1 Beauty: Creating Beautiful Web Apps in Laravel 5.1](https://www.amazon.co.jp/dp/B0113VALD0)」という電子書籍です。ブログサイトがもとになっていて、記事の通り手を動かしていくとそのブログシステムそのものが出来上がるという企画でした。結構面白かったし役にも立ちましたが、そのときはそういう手を動かす系の日本語コンテンツは見つけられなかったです。いまはブログや電子書籍で少しずつ出てきているのかもしれませんが。

書店で買えるフレームワーク本には体系立った構成が多いですが、そのぶんページ数が多くて読みきれず、全体像が掴みにくいと感じます。内容によっては説明ばかりで何も作らないので面白くないし。あと Laravel に関してはドキュメントが充実しているのでわざわざリファレンス的な文献を買う必要がないです。

始めの一歩に必要なのはMVCパターンについての詳しい説明でもメソッドのオプション一覧でもなく、実際こういう感じで作っていくんだ、というガイダンスだと思います。プログラミングパターンは作り続けないと絶対理解できないし、オプション一覧は調べれば分かりますよね。ゼロからアプリを作るプロセスを示してあげて、そのあとは自然と自分で歩いていけるようになるのが、素敵な学習体験かなと。

というわけで、Laravel 開発を仕事でも何度か経験して慣れたところで書いてみました。
誰かのエンジニアデビューのきっかけになれば幸いです :innocent:

:game_die: :game_die: :game_die:

ちなみに休日などに少しずつ書いて、まる一ヶ月かかりました。
もう少しペースアップしたい。

次は Laravel & Vue.js のチュートリアルを書こうかなと考えてます。
業務で使うGitコマンドはGUIでも使用できるのか

# 概要
入社してからGitコマンドをCUI上で使えるようになりました。
:girl_tone1:「実はこれGUIでもできるんじゃない？」
と思ったのでトライしました。


# 使ったクライアントアプリ
Source Tree[^1]

# トライする項目
下の表は、私が業務で使うコマンドの中で
GUIで使用したことが (ある:○/ない:×) をまとめたものです。
今回は、No.6〜No.9にトライします。 

| No | コマンド | 使用したことが (ある:○/ない:×)  |
| :---------- |:-----------|------------:|
| 0 | add | ◯ |
| 1 | commit | ◯ |
| 2 | pull | ◯ |
| 3 | merge | ◯ |
| 4 | stash | ◯ |
| 5 | fetch | × |
| 6 | commit --allow-empty | × |
| 7 | cherry-pick | × |
| 8 | revert | × |
| 9 | commit --amend | × |


## $ git commit --allow-empty
シェルスクリプトを書いてインポートすればできる。ちょっと手間だな..:confounded:

## $ git cherry-pick
コミットメッセージを右クリックして「チェリーピック」を選択。
 `git log`でコミットIDを見る手間が省けます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316832/290af200-eac5-529a-3c9b-9f7163554742.png)

## $ git revert
コミットメッセージを右クリックして「コミット適用前に戻す」を選択。
 こちらも、`git log`でコミットIDを見る手間が省けます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316832/f5abea7d-dad1-ad22-c349-535d358a3e14.png)


## $ commit --amend
`git rebase　-i`で代用するやり方しかわかりませんでした😩

変更したいコミット以前のコミットメッセージを右クリックして「＊＊＊の子を対話形式でリベース」を選択。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316832/44cb023b-e729-bec4-0172-79db791a4d61.png)
コミットメッセージをダブルクリックすると編集画面が出てきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316832/b8d24585-ffad-6ad0-677a-79e613cdb26b.png)

# 結論
- 業務で使うGitコマンドはGUIでもほとんどは使用できる:ok_woman_tone1:
- コマンドにオプションを指定して使うのはGUIでは少々厳しかった。特に、履歴を変更する操作は
CUIの方ができることの幅が広がる上に理解しやすい:raised_hand_tone1:
- 業務では`git commit --allow-empty`の使用頻度が高いのと、Git以外の操作(ディレクトリ間の移動、npmなど)も多く、画面移動が少なくて済むCUIは総合的に使いやすい:raised_hand_tone1:
- 個人的に、`git checkout`をいつもタイポしてしまうので[^2]、GUIのワンクリックでチェックアウトできる点に一番魅力を感じた:ok_woman_tone1:




[^1]: https://ja.atlassian.com/software/sourcetree
[^2]: この記事を書いているときにもタイポした。
Djangoアプリの開発環境をKubernetes(minikube)に構築する方法

## はじめに

[Gaiax Group Advent Calendar 2018](https://qiita.com/advent-calendar/2018/gaiax-group)の10日目の記事です。

インターン生ながらナチュラルにアドベントカレンダーに参加させてもらえて嬉しい限りです。
今回は、頭の中を整理することも兼ねて、ローカルにDjangoアプリをKubernetes上に構築する方法をまとめました。

## 目次

- 前提
- プロジェクトの作成
- Dockerfileの作成とビルド
    - 作成
    - ビルド
- Kubernetesへデプロイ
    - Kubernetes yamlファイルの作成
    - デプロイ
    - ブラウザで確認
- あとがき
- 参考

## 前提

- pipenvとpyenvを導入済み
- dockerを導入済み
- minikubeを導入済み

## プロジェクトの作成

pipenvでDjangoプロジェクトを作成します。[Djangoのチュートリアル](https://docs.djangoproject.com/ja/2.1/intro/tutorial01/)をご参考ください。

```bash
$ touch Pipfile
$ pipenv --python=3.7.1
$ pipenv install django
$ pipenv run django-admin startproject config .
```

実際はALLOWED_HOSTSを動的に設定する必要がありますが、今回の例ではALLOWED_HOSTSを全許可しておきます。

```python
# ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']
```

## Dockerfileの作成とビルド
### 作成

```dockerfile
FROM python:3.7.1

RUN mkdir /code/
COPY ./ /code/
WORKDIR /code/

RUN pip install --upgrade pip && \
    pip install pipenv && \
    pipenv --python /usr/local/bin/python
RUN pipenv install

CMD pipenv run python manage.py runserver 0:8000
```


### ビルド

ビルドの前に、ホストマシンではなくminikubeのDockerを使用するように設定を変更します。

```bash
$ eval $(minikube docker-env)
```

この状態で、 `latest` 以外のタグを付けてビルドを行います。

```bash
$ docker build -t sample/django:v1 .
```

## Kubernetesへデプロイ

### Kubernetes yamlファイルの作成

下記の内容を `k8s-django.yaml` などのファイル名で保存します。

```yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: django
spec:
  replicas: 1
  selector:
    matchLabels:
      app: django
  template:
    metadata:
      labels:
        app: django
    spec:
      containers:
        - name: django
          image: "sample/django:v1"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8000
              name: django
---
kind: Service
apiVersion: v1
metadata:
  name: django-svc
spec:
  selector:
    app: django
  ports:
    - protocol: TCP
      port: 8000
      name: django
  type: NodePort
```

### デプロイ

```bash
$ kubectl create -f k8s-django.yaml
```

### ブラウザで確認

サーバーが起動したことをブラウザで確認します。

```bash
$ minikube service django-svc
```

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/177433/9f10fb63-08e6-d6e1-4d38-12899500b4ea.png" width=50%>
</div>

:tada: :rocket: :tada:

## あとがき
今回はminikubeでDjangoアプリのデプロイをしてみました。
ホストマシンからminikube内のアプリにアクセスするのが思ったより難しいですね。

`k8s-django.yaml` にDjangoアプリを作成しましたが、同様にDBのyamlを定義してやることで、簡単にDBと接続させることが可能です。
yamlファイルをそのままGKEなどに使いまわしてデプロイできるので、開発ではdocker-compose、本番はk8sみたいな環境に比べると利便性高いですね！

## 参考
- [minikubeでローカルのdocker imageを使う - Qiita](https://qiita.com/ocadaruma/items/efe720e46ae7ecb9ec25)
[クローリングハック]メモ1

# INFO

こちらは
[クローリングハック](https://www.amazon.co.jp/%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E3%83%8F%E3%83%83%E3%82%AF-%E3%81%82%E3%82%89%E3%82%86%E3%82%8BWeb%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E5%AE%9F%E8%B7%B5%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-%E7%AB%B9%E6%B7%BB-%E7%9B%B4%E6%A8%B9/dp/4798150517/ref=sr_1_1?ie=UTF8&qid=1544448515&sr=8-1&keywords=%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E3%83%8F%E3%83%83%E3%82%AF)1章目のメモになります。(2章目もちょっと入ってる)

僕がしらないことだけメモしているの内容に偏りがあります。

# WARNING

typoなど多めです。


## curlコマンド

```
curl -iでヘッダーも取得
curl -Iでヘッダーのみ取得
(これがHEADリクエストだったんだ！
last-modifiedヘッダを確認してGETするときとかに便利。)
curl -Aでuser-agent情報の追加
curl -x post url -d username=suzuki
-dで送信する内容
jsonを送るときはシングルクォートで囲むと
改行して送信できるので便利。

-d '{
  username: "suzuki"
}'

curl --verboseオプションで
すべてのリクエストとレスポンスが見れる。
> リクエストヘッダ
< レスポンスヘッダ
```



## クローラー時に気をつけること

user-agentヘッダには、
クローラーの説明ページのURLと、取得する情報の用途を。

robots.txtを最初に確認しよう。


## 便利

クローラーのwebサイト:
import.io
クロムの拡張機能:
scraper

## 他

HTTPは基本的に「1つのリクエストに対して、1つのレスポンスを返す」プロトコル。
(この表現面白い、逆に複数レスポンスがあるもの知りたい。)

```
**HTTPリクエスト**  
リクエストライン
リクエストヘッダ
空行
リクエストボディ
```

```
**HTTPレスポンス**
ステータスライン
レスポンスヘッダ
空行
レスポンスボディ
```



> HTML5は、GET・POST以外のリクエストを送信することができないために、
Rails5などではname="_method" value="post"のような書き方が見られた。
(擬似的に表現)

>JSONやXMLなどをリクエストボディとして
送信したい場合はX-HTTP-METHOD-OVERRIDEの設定。

>XMKHttpリクエストならばput、deleteメソッドが使える。

>Remote Procedure Callは、
処理の内容をボディに書く(REST以外に初めて見た！)


>405はMethod Not allowed
501はnot implemented

>rel="nofollow"と書けばクローラー対象外に
(SEO関連の話で聞いたことある)

>www.example.com
サブドメイン.ドメイン.トップドメイン 
(順番へん！w)


>クローリングする前は
エンコードを確認する！

>例えば、半角は
RFC3986だと%20
POSTメソッドのapplication/x-www-form-unlencsdedは+
Mojaveにアップデートしたらalfredのクリップボードが使えなくなったときの対策

System Preferences > Security & Privacy > Privacy から Accessibility で Alfred を許可すれば良い。

[Alfred on macOS 10.14 Mojave - Alfred Help and Support](https://www.alfredapp.com/help/getting-started/macos-mojave/)

ちなみにalfredのクリップボード履歴はpower pack限定機能だけど、圧倒的に便利なのでぜひ使ってみて。
Mbedドライブへbinコピー後に自動リセット

12月5日、SeeedはArmが主催する[Mbed Connect](https://www.armkk-event.com/mc/)の、Workshop「Arm MbedでセルラーIoTを実装してみよう」での出来事。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/e16d93ba-f4e5-2044-1e3a-c9be47214c66.png)

Wio 3G(+microSD)とMbedオンラインコンパイラを使って、[ハンズオンテキスト](https://seeedjp.github.io/handson/PelionWS-Wio3G/)に沿って進めるセルフハンズオンでした。

参加者から
「テキスト間違ってるよ。リセットの記述が合っていない。」
という指摘が。

１箇所は、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/54beec51-2c8b-bc5e-550e-a81ef4f605c8.png)

で、もう１箇所は、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/9eec4d66-fa9d-1cb4-a45c-afd0837e4276.png)

．．．確かに間違っていました。スイマセン。


じゃあ、正しいのはどっちだ！？という話になったときに、

参加者A「リセットされなかったから、BLボタンを押した。」
参加者HOGE「勝手にリセットされたぞ。」

んん？
どういうこと？



．．．



あぁ、Wio 3Gが1台調子悪かったので、代わりにわたしが使っているWio 3Gを出したのが原因でした。（それを参加者HOGEさんが使っていたというわけ）
普段使いしているやつで、ちょっと設定が違うので自動リセットされたんですエヘヘ。

# デフォルトは手動リセット

プログラムをコンパイルしてデバイスで実行するとき、.binファイルをMbedドライブにコピーしますが、このときMbedインターフェースチップ（DAPLink）は.binをターゲットMPUのフラッシュ領域に書き込みします。書き込んだ後は停止したままなので、BLボタンをクリックして、ターゲットMPUを起動（再起動？）させる必要があります。

# リモートでリセット操作

でも、物理ボタンのBLボタンをクリックするのって面倒ですよね？
ちょっと手を伸ばさないといけないし、、、基板を壊さないように慎重に扱わないといけないですし。

実は、DAPLinkの仮想シリアルポートにbreak信号を送る、という手法でキーボードから手を放さずにリセット操作することができるんです！

詳細は、、、[こちら](https://os.mbed.com/users/ytsuboi/notebook/langja-how-to-reset-with-break/)に記事があるのでご覧ください。

# 自動リセット

さらに、DAPLinkを設定変更すると、Mbedドライブに.binファイルをコピーした後、自動でリセットさせることが可能なんです！！！

やり方は簡単。
パソコンに`auto_on.cfg`という名前のファイルを作って、Mbedドライブにコピーしてください。
たったこれだけ。

詳細は、、、[ここ](https://github.com/ARMmbed/DAPLink/blob/master/docs/MSD_COMMANDS.md)にあります。

お好みのリセット手段をお楽しみください♪
非asyncメソッドからasyncメソッドを使う拡張メソッド(リベンジ)

[去年書いたやつ](https://qiita.com/albireo/items/7deaaba69be84320ce9e)がクソすぎたのでけっこう後悔していたんだけど、今日気がついたやりかた。

```csharp:@laughterさんが修正してくれた改良前のコード
static class TaskExtention {
  //返り値なし
  public static void NoWait(this Task task, Action<Task> action = null, CancellationToken? ct = null)
  {
    if (action != null) {
      if (ct != null) {
        task.ContinueWith(action, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(action).ConfigureAwait(false);
      }
    } else {
      if (ct != null) {
        task.ContinueWith(_ => {}, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(_ => {}).ConfigureAwait(false);
      }
    }
  }

  //返り値あり
  public static void NoWait<TResult>(this Task<TResult> task, Action<Task<TResult>> action = null, CancellationToken? ct = null)
  {
    if (action != null) {
      if (ct != null) {
        task.ContinueWith(action, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(action).ConfigureAwait(false);
      }
    } else {
      if (ct != null) {
        task.ContinueWith(_ => {}, (CancellationToken)ct).ConfigureAwait(false);
      } else {
        task.ContinueWith(_ => {}).ConfigureAwait(false);
      }
    }
  }
}
```

###改良版
@laughter さんの修正案コメント

> ??とCancellationToken.Noneを使うとキャストを消せる

を見て「パラメータ省略時の値にCancellationToken.None」を指定できたらもっとすっきりするのになー」と思ってたら、[default(CancellationToken)と書くことで可能](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.cancellationtoken.none?redirectedfrom=MSDN&view=netframework-4.7.2#%E6%B3%A8%E9%87%88) アンド `task.ContinueWith(action, CancellationToken.None)`は`task.ContinueWith(action)`と同等との記述を見つけたのでさらに改良。
ついでにactionの方の扱いも修正して、if文のネストがごっそりなくなりました。

```csharp
static class TaskExtention
{
  //返り値なし
  public static void NoWait(this Task task, Action<Task> action = null, CancellationToken ct = default)
  {
    task.ContinueWith(action ?? (_ => { }), ct).ConfigureAwait(false);
  }

  //返り値あり
  public static void NoWait<TResult>(this Task<TResult> task, Action<Task<TResult>> action = null, CancellationToken ct = default)
  {
    task.ContinueWith(action ?? (_ => { }), ct).ConfigureAwait(false);
  }
}
```

###使い方

```csharp:使い方
void NoAsyncMethod(CancellationToken ct)
{
  //返り値なし、後処理なし
  AsyncMethod().NoWait();

  //返り値あり、後処理あり、CancellationTokenあり
  AsyncMethodWithResult(ct).NoWait(task => { var result = task.Result; }, ct);
}
```

呼び出し側で実行結果を受け取ることはできない。
「呼び出したいメソッドがasyncなやつしかないけど、呼ぶ側はasyncにできない。処理完了を待ったり結果を受け取る必要はなくて投げっぱなしでOK」といったケース用のお手軽メソッドなので、そういう制約を気にする必要がないときに使うものです。
juliaでPlots.jl  枠のデザイン framestyleで設定可能　GRを使用

`Julia: ver1.0.2`
`GR: 0.36.0`
参考: https://docs.juliaplots.org/latest/examples/gr/
のFramestyleのところ

# 論文用などで，枠で囲いたい時

```
using Plots
Plots.gr()
plot([1,2,3], framestyle=:box)
```
<img width="600" alt="julia_gr2.png" src="https://qiita-image-store.s3.amazonaws.com/0/164411/7192d2eb-6a5a-6768-fba0-c6b330bc7ce4.png">

できれば，上の枠と右の枠にも目盛りを入れたいのだが，そのオプションが見つからなかった．．．
知っている人いれば，教えて頂けると嬉しいです．
keras 2.2.4でInputLayerを使ったモデルを保存すると壊れる

keras初心者です。

tl;dr
-------------

掲題の通り。see: https://github.com/keras-team/keras/issues/11683

私の場合、[Issueを上げた人のパッチでは治りませんでしたが](https://github.com/keras-team/keras/issues/11683#issuecomment-435620108)、[そのあとのこちらのコメント](https://github.com/keras-team/keras/issues/11683#issuecomment-435836253)を見て、直したら使えるようになりました。

他にも[Dropoutを最初の層に持ってきたりする](https://github.com/keras-team/keras/issues/10417#issuecomment-416951896)と壊れるそうですが、そちらは確認してません。


例
------------

ある日、こんな感じのモデルを書きました。よくある分類する感じのやつです。

``` py
from keras.models import Sequential
import keras.layers as L

def MyConv3DModel(IMAGE_SHAPE, TIMESTEP, CLASSES):
    '''
    Parameters
    ----------
    IMAGE_SHAPE: (int, int, int)
        画像の情報(縦,横,チャンネル数)
    TIMESTEP: int
        フレーム数
    CLASSES: int
        分類する数

    Return
    -------
    もでる。

    '''
    model = Sequential()
    # 以下の行が問題
    model.add(L.InputLayer(input_shape=(TIMESTEP, IMAGE_SHAPE[1], IMAGE_SHAPE[0], IMAGE_SHAPE[2])))
    model.add(L.Conv3D(32, (3,3,3), strides=(2,2,2), activation='relu', name="Conv3D-1"))

    # 中略

    model.add(L.Dense(CLASSES, activation='softmax'))
    return model
```

で、学習途中でも結果を保存したいので、kerasの学習(fit)時コールバックにこんな感じのコードを書きます。

```
    keras.callbacks.ModelCheckpoint("path/to/weights.{epoch:02d}-{val_loss:.2f}.hdf5",
                                    verbose=1,
                                    save_weights_only=False, # レイヤも保存する
                                    period=1),
```

hdf5ファイルもちゃんと作られるんですが、掲題の問題で、**InputLayerを明示的に宣言すると、読めなくなる**という現象が発生しています。

InputLayerがあるとダメなようで、InputLayerを削除して代わりにinput_shapeを渡すようにすれば良いみたいです。

``` py
    model = Sequential()
    model.add(L.Conv3D(32, (3,3,3), strides=(2,2,2), activation='relu', name="Conv3D-1", input_shape=(TIMESTEP, IMAGE_SHAPE[1], IMAGE_SHAPE[0], IMAGE_SHAPE[2]))) # これは良い
```


幸い、Issueにてhdf5ファイルを修正してうまく動くようにする方法が紹介されています。

なので時期アップデートで治るとは思うので記事にするまでもないと思うのですが、音沙汰がない期間があったり、Botが勝手にクローズしたりと変な感じです。（ワークアラウンドがあるなら後で良いな感。）

私はkerasもtensorflowも中身を知らずに使っているので、修正しようにもさっぱりわからない。


スクリプトに仕立てた
------------------------

モデルを書き直せば良いんですが、数十時間学習させて作った重みを再度学習しなおすのは辛かったのと、元ネタの修正内容が破壊的だったので、コピーを取ってから行うように修正することにしました。コードを貼っておきます。

https://gist.github.com/fukasawah/e1428a426846ffd6ab858f5a4e5a059d

```
# 使用例: Convolution3Dで1920x1080x3画素の画像データを60個扱うようなモデルを作った場合 (縦と横に注意)
python hdf5_fix_layer0.py filepath.hdf5 60 1080 1920 3
```

修正版は"filepath.hdf5.fixed"という形になります。
ConfluenceとGoogle Driveで、社内向けPodcastをカジュアルに配信する

社内向けPodcastをカジュアルに配信する方法をまとめました。

:microphone2: Podcastを配信してみたい方のお役に立てば幸いです。


## Podcastの録音・配信方法

録音機材とアップロード先さえあればなんとか形になります。

手順はこんな感じです。

- ボイスレコーダーで録音
- Google Driveに収録した音声データを置いて、共有ファイルにする
- Confluenceに、配信用のhtmlスニペットを追加
- ドキュメントのリンクをシェアする

## 配信画面と設定方法

ConfluenceにPodcast用のaudioタグを記述します。
**再生速度を変更できるボタンを付けているので、サクッと聞くことができます。**

<img width="1257" alt="スクリーンショット_2018-12-10_20_12_39.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/18114/de7fcfb7-8dc1-e8a3-0027-7344f135a8a7.jpeg">


上記Podcast再生用の部分には、以下htmlを埋め込んでいます。
id部分はGoogle Driveに置いた録音ファイルのidにリプレイスするだけなので簡単ですね。

```html
<script type="text/javascript">
AJS.toInit(function(){
	AJS.$(".playRateButton").on("click", function() {
		var media = document.getElementById("media");
		var playRate = AJS.$(".playRate").val();
		media.playbackRate = playRate
		media.play();
	});
});
</script>
<audio id="media" autobuffer="true" controls="true" preload="none"  style="width: 500px">
<source src="https://docs.google.com/uc?id=**********"></source>
Your browser doesn't support HTML5 audio.
https://drive.google.com/file/d/**********/view?usp=sharing
</audio><br>
<input style="width: 30px" class="playRate" type="number" step="0.1" value="1.5">
<button class="playRateButton">倍速</button>
```

## シェアする

このConfluenceのURLを、SlackなりChatworkなりでシェアすれば、カジュアルにPodcastを配信することができます！

## まとめ

Confluenceでなくてもhtmlを差し込めるようなドキュメントツールであれば大丈夫だと思います。
**とても簡単に再生速度変更付きPodcastを作ることができます**ので、是非お試しください！
[論文メモ] Enriching Word Vectors with Subword Information

# 前置き
- [Enriching Word Vectors with Subword Information](https://arxiv.org/abs/1607.04606)
- fasttextの論文

# アルゴリズムの概要
- word2vecに代表されるskip-gramによるembeddingを拡張したもの。
- 単語だけでなく、単語のn-gramも考慮することで高速かつ高精度にembeddingができるようになった。

## 準備: Skip-gramモデル
- skip-gramモデルは下記の対数尤度を最大化するモデル。

$$\sum_{t=1}^T \sum_{c \in C_t} \log p(w_c|w_t)$$

- $C_t$は$w_t$のまわりにある単語のインデックスの集合
- 確率はsoftmaxを使って下記のように定義する。

$$p(w_c|w_t) = \frac{e^{s(w_t, w_c)}}{\sum_{j=1}^W e^{s(w_t, j)}}$$

- 実際にはnegative samplingを行い下記の最大化する。

$$\sum_{t=1}^T \sum_{c \in C_t} l(s(w_t, w_c)) + \sum_{n \in N_{t,c}} l(-s(w_t, n))$$

- $N_{t,c}$はサンプリングされたnegative exampleの集合
- $l(x)=\log(1 + e^{-x})$

- またスコアリング関数$s$はembedding同士の内積とする。

$$s(w_t, w_c) = u_{w_t} \cdot v_{w_c}$$

- ここで$u_{\cdot}$と$v_{\cdot}$は違うものであることに注意。

## Subword model
- 単語$w$のn-gramの集合を$\cal{G}_w \subset \\{1,...,G\\}$とする。
- n-gram $g$のembeddingを$z_g$とし、各単語のembeddingをその単語のn-gramのembeddingの合計とする。
- このときスコアリング関数$s$を下記のように定義する。

$$s(w, c) = \sum_{g \in \cal{G_w}} z_g \cdot v_c$$

- ここで常に単語$w$は$\cal{G}_w$に含まれるにようにする。
    - ただし、n-gramとしての文字列と単語のとしての文字列が一致しても別のembeddingを持つ。
    - 例えば、単語としてのasとpasteの中に含まれる2-gramのasは別のembeddingを持つ。
- このように単語間でn-gramを通じて同じembeddingを共有することでレア単語に対しても有効なembeddingを学習できる。

## Dictionary of n-gram
- $\cal{G_w}$の定義に設定の余地がある。
- この論文では下記のような設定を提案している。
    - 3以上6以下のn-gramを使う。
    - 別途、prefixやsuffixを追加する。
    - ただし最も頻出する上位P個の単語に関してはn-gramを使用しない。

# 使い方
- fasttextは[fasttext.cc](https://fasttext.cc)で公開されている。
- またgensimにwrapperがあるのでword2vecと同じように使えて便利。[gensimのfasttextのtutorial](https://radimrehurek.com/gensim/models/fasttext.html)
バリュー・カード

この記事は、[Pepabo Managers Advent Calendar 2018](https://adventar.org/calendars/3264) の10日目の記事です。 

自身は、SUZURI事業部でエンジニアやデザイナーが集まるチームのマネージャーをしております。

本日は、この機会を使い「バリュー・カード」をご紹介させていただきます。
一度見ていただくのが早いかと思います。以下のようなものです。

<img width="1399" alt="mayotoのバリュー分類シート (2016:12:31).png" src="https://qiita-image-store.s3.amazonaws.com/0/6342/3758a763-b0c5-bf9c-7709-805c09206382.png">

※画像: 私が2016年12月に分類したバリュー
※カードの1つ1つの説明は記事の最後にある Trello のボードから見ることができます

「バリュー・カード」は、こちらの書籍で知ることになりました。

[組織改革―ビジョン設定プロセスの手引](https://www.amazon.co.jp/dp/4306011542)

バリュー・カードの説明は、以下に書籍の内容を引用させていただきます。

> バリューカードは、個人とグループのバリューを明確にするための手段です

> 特定のバリューを示した48枚のカードを「あなたの人生においてそのバリューがどの程度中心的なものにでありかつ重要なものであるかを示すように、各区分にバリュー・カードを配置する。それぞれの列に最大で10枚のカードを配置するようにカードを分類する。」

> 「最も重要なカードを列の一番上に、最も重要でないものを一番下に置く。48枚のすべてのバリューを重要性の高いものから低いものへと分類した結果が得られる。」

このバリュー・カードを実際に分類してみることで自分がその時に、何を大切にしているかを示すことができます。

つい先日、私が所属するSUZURI事業部でこれからのビジョンやミッションのようなものを考える場があり、進めていくメンバーから私の考えについてヒアリングしていただきました。その際に、私がこうしたいと考えている根本的なところに、このようなことを大切にして生きているからですと、このバリュー・カードを見せながら説明でき大変役に立ちました。

また、このことをきっかけに「今」の自分はどうなんだろう？先日、改めて分類してみた結果がこちらです。

<img width="1398" alt="mayotoのバリュー分類シート (2018:12:10).png" src="https://qiita-image-store.s3.amazonaws.com/0/6342/aa11a457-512c-27fa-aaa5-de01dabf8655.png">

※画像: 私が2018年12月に分類したバリュー


2016年と2018年の比較（バリューは常にある、バリューはおおむねある）

社会的責任: 6 → 4
熟練: 0 → 4
相互関係: 5 → 2
継続性: 4 → 3
ライフスタイル: 1 → 4
自己開発: 4 → 3

カードの種類である熟練とライフスタイルがプラスに大きく変わっています。
一方、社会的責任、相互関係、継続性、自己開発がマイナスに変わっています。

熟練のカードには自身を鍛錬するようなカードが多く、ライフスタイルには自身の生活にまつわるカードが多いため、それらを他より優先順位を上げてでも重視したくなっていると、自身が分類した結果から自己分析できます。（書籍にはより詳しく説明されています）

このようにバリューを明確にすることは個人や組織において大切なものです。
特に組織においては価値観を共有することが大事であるとお考えの方は多くいらっしゃると思います。
そのような際に、このバリュー・カードはひとつのフレームワークとして使えるものになるでしょう。

ぜひみなさんも個人やチームでやってみてはいかがでしょうか。
（きっと分類するのにとても悩み、時間かかると思います。での自身と向き合えてなんだか気持ちがすっきりしますよ。）

まとめるのが下手ですがこの辺でこの記事をおわりにしたいと思います。 :joy: 

#### 画像のシートについて

私はバリュー・カードを分類するにあたって、カードが自由に動かせる Trello が最適なツールと考え利用しました。

以下に公開ボードとして作成しましたので、ご自身でもお試しされたい方は、ぜひコピーしてお使いください。

[Trello バリュー・カード](https://trello.com/b/m2b2Ib3I)

#### その他

- バリュー・カードはチェンジワークス社のコピーライトです。（書籍p29より）
  - そのため私が権利を主張するものではございません
- 海外では「Personal Values Card Sort」と言われているようです。
bpi:bit の MicroPython その２

９日目に続けて bpi:bit 用 MicroPython について書きます。昨日は MicroPython のファームウェアをインストールするところまででした(12/10 に新しい firmware.bin がリリースされました)。本日は mpfshell というツールを使って Hello World を実行します。

# mpfshell ツール

mpfshell はリモートで MicroPython ボードを操作するためのツールです。Windows 版は [bpi:bit MicroPython ダウンロードサイト](https://github.com/BPI-STEAM/BPI-BIT-MicroPython/releases)に `Windows-Mpfshell.exe` という名前であります。Linux や macOS の場合は `intellij-mpfshell-1.1.1.zip` をダウンロードして、展開した中にある scripy/mpfshell.py を使います。

起動はたとえば、macOS の場合では 次のようにします。シリアルポートの指定は起動してからでも open コマンドで指定できます。シリアルポートの `/dev/` は省略できます。

```
$ python3 mpfshell.py cu.wchusbserialfa1440 

Documented commands (type help <topic>):
========================================
EOF  close     get   lexecfile  ls    mput  open  quit  runfile
cat  exec      help  lls        md    mpyc  put   repl
cd   execfile  lcd   lpwd       mget  mrm   pwd   rm  

Undocumented commands:
======================
c  e  ef  lef  o  q  r  rf

All support commands, can input help ls or other command if you don't know how to use it(ls).
looking for computer port...
serial name : cu.Bluetooth-Incoming-Port
serial name : cu.wchusbserialfa1440
input ' open cu.wchusbserialfa1440 ' and enter connect your board.
Connected to esp32

** Micropython File Shell v0.8.1, sw@kaltpost.de & juwan@banana-pi.com ** 
-- Running on Python 3.6 using PySerial 3.4 --

mpfs [/]> 
```

mpfshell を使えば、Unix/Linux 風のコマンドで bpi:bit を操作できます。ls や cat を使って bpi:bit のファイルシステムにあるファイルを操作できます。

```
mpfs [/]> ls

Remote files in '/':

       boot.py
       wifi_cfg.py

mpfs [/]> cat wifi_cfg.py
WIFI_SSID = 'webduino.io'
WIFI_PSWD = 'webduino'
HOST_NAME='bit2438'

mpfs [/]> 
```

# Wi-Fi の設定

さて、今 cat コマンドで wifi_cfg.py の中身を見ましたが、bpi:bit の Wi-Fi 設定はこのファイルで行います。これを自分の環境用に直しておかないとシリアルに `no AP found` というメッセージは頻繁に出でうるさいので、ここで直してしまいましょう。実際は正当な設定ツールがあるのですが、けっこうまだるっこしいしいので直接このファイルを更新します。 wifi_cfg.py の中身は次もフォーマットです。

```python
WIFI_SSID = "WiFiアクセスポイント"
WIFI_PSWD = "WiFiアクセスポイントのパスワード"
HOST_NAME = "ボードのネットワーク名"  # オプション
```

これを自分の Wi-Fi 環境用に設定したファイルを用意してから、以下のようにして mpfshell の put コマンドで転送します。

```
mpfs [/]> put wifi_cfg.py
mpfs [/]> 
```

# REPL の起動

mpfshell から repl コマンドを実行すると REPL が起動します。おなじみ "Hello, World!" を print してみましょう。

```
mpfs [/]> repl

*** Exit REPL with Ctrl+] ***>

MicroPython v1.9.4-817-g72effc642-dirty on 2018-12-10; ESP32 module with ESP32
Type "help()" for more information.
>>> print('Hello, World!')
Hello, World!
>>> 
```

このボードのちょっとおもしろいところは microbit モジュールが用意されていて、micro:bit の LED スクロールなどがそのまま使えるところです。

```python
>>> import microbit
>>> microbit.display.scroll('Hello, World!')
>>> 
```

![bpibit_hello.gif](https://qiita-image-store.s3.amazonaws.com/0/106817/9bc1bec8-3c56-563a-d56c-eb8e7e1aa8e5.gif)

本日はここまです。サンプルコードは [github](https://github.com/BPI-STEAM/BPI-BIT-MicroPython)にたくさん用意されているので、bpi:bit を持っていたら試してみてください。
Goでsqlxを使う

##Goのデータベース系ライブラリ sqlxとは
GoでDB接続に使う標準パッケージdatabase/sqlに拡張機能を提供するライブラリです。
DBから引っ張ってきたデータを構造体、マップ、スライスに当てはめてくれます。
##何が良いのか
通常であればデータベースから引っ張ってきたデータをカラムごとに一個一個Scan（型変換）しなければなりませんが、そこを勝手にやってくれるのでコード記述量を少なくできます。カラム数が多いレコードを全件引っ張ってくる時なんかは、とても便利です。
これ以外にも用途があるのかもしれませんが、今の所わかったこと。

##使い方
使わないと分からないと思うので具体例で見てみます。
今回はMysqlにあらかじめ用意しておいた、id, name, ageカラム があるだけのシンプルなデータベースに接続してみます。あらかじめ２件のレコードを挿入してあります。
<img width="455" alt="スクリーンショット 2018-12-10 21.52.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/260824/c23402f3-0164-d3ca-bb7e-369862909257.png">


まずはライブラリをgo getしておきます。
https://github.com/jmoiron/sqlx

```
go get github.com/jmoiron/sqlx
```

続いて、引っ張ってきたデータを構造体に当てはめる、もっともシンプルなコードの記述例です。

```go
package main

import (
	"fmt"
	"log"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

//引っ張ってきたデータを当てはめる構造体を用意。
//その際、バッククオート（`）で、どのカラムと紐づけるのかを明示する。
type User struct {
	ID   int    `db:"id"`
	Name string `db:"name"`
	Age  int    `db:"age"`
}

type Userlist []User

func main() {

	//Userデータ一件一件を格納する配列Userlistを、Userlist型で用意
	var userlist Userlist

	//Mysqlに接続。sql.Openの代わりにsqlx.Openを使う。
	//ドライバ名、データソース名を引数に渡す
	db, err := sqlx.Open("mysql", "root@/gosample")
	if err != nil {
		log.Fatal(err)
	}

	//SELECTを実行。db.Queryの代わりにdb.Queryxを使う。
	rows, err := db.Queryx("SELECT * FROM users")
	if err != nil {
		log.Fatal(err)
	}

	var user User
	for rows.Next() {

		//rows.Scanの代わりにrows.StructScanを使う
		err := rows.StructScan(&user)
		if err != nil {
			log.Fatal(err)
		}
		userlist = append(userlist, user)
	}

	fmt.Println(userlist)
	//[{1 yamada 25} {2 suzuki 28}]

}

```

通常のsqlパッケージであれば、rows.Nextのところで「&user.ID,$user.Name...」などとカラム の分だけ引数を書かなければなりませんが、sqlxを使うと、当てはめたい構造体の構成まで見に行ってくれるので　、ここでは「&user」と書くだけ済んでいます。
今回は3つしかカラム がないので全部書いてもそれほど面倒ではありませんが、カラム数が多いレコードの場合はとても便利です。

##参考
公式
https://github.com/jmoiron/sqlx
http://jmoiron.github.io/sqlx/
JavaScript 分割代入（デストラクチャリング）

JavaScript の分割代入を使うと、オブジェクトや配列からプロパティを取り出して、複数の変数に代入できます。

```js
const obj = {  
  a: 1,
  b: 2,
  c: 3
}
const {b, c, d} = obj // 分割代入
console.log(b) // 2
console.log(c) // 3
console.log(d) // undefined
console.log(a) // Error
```

## 宣言済みの変数への代入は注意

```js
const obj = {  
  a: 1,
  b: 2,
  c: 3
}
let a, b, c

({a, b, c} = obj) // () で囲む
{a, b, c} = obj // エラー
```

 `{}` をブロックだと判断されてしまうため、 `()` で囲む必要があります

## 異なる名前に代入も可能

```js
const obj = {  
  a: 1,
  b: 2,
  c: 3
}
const { a: x } = obj
console.log(x) // 1
```

変数　`x` に `obj.a` を代入しています

## スプレッド演算子を使えば、残りすべてを代入可能

```js
const arr = [1, 2, 3, 4]
const [x, ...rest] = arr
console.log(x) // 1
console.log(rest) // [2, 3, 4]
```

## 配列の分割代入を使えば、変数の値入れ替えが簡単に

```js
let a = 5
let b = 10
[a, b] = [b, a]
console.log(a) // 10
console.log(b) // 5
```

## デフォルト値を設定可能

```js
const obj = {  
  a: 1,
  b: 2,
  c: 3
}
const { a = 10, x = 100 } = obj
console.log(a) // 1
console.log(x) // 100
```

デフォルト値の設定は、非常に便利なので具体的な例を詳しく確認しておきます。

```js
function foo ({ a = 100, b = 200 }) {
  console.log('a', a)
  console.log('b', b)
}

foo({
  a: 1
})
// a 1
// b 200

foo({
  b: 2
})
// a 100
// b 2
```

関数の宣言で、 `{ a = 100, b = 200 }` という引数が書かれています。
ここは次のコードでも同じ意味です。

```js
function foo ({ a, b }) {
  if (a === undefined) {
    a = 100
  }
  if (b === undefined) {
    b = 200
  }
  console.log('a', a)
  console.log('b', b)
}
```

上記の `{ a, b }` の部分、Vue の [Vuex](https://vuex.vuejs.org/guide/mutations.html#commit-with-payload) でよく出てきます。Vue を書いていると結構出てくるコードですが、なんとなく書いている方も多いような印象です。このように **分割代入** はよく利用される書き方なので、押さえておく必要があります。

また、次のコードも同じように動きます。

```js
function foo (payload) {
  const a = payload.a === undefined ? 100 : payload.a
  const a = payload.b === undefined ? 200 : payload.b
  console.log('a', a)
  console.log('b', b)
}
```

上記の `payload` は関数の引数の書き方としては一般的な書き方ですので、分かりやすいかもしれません。

## まとめ
分割代入（デストラクチャリング Destructuring assignment）は便利！

## 引用
- [O'Reilly 初めてのJavaScript第版 ES2015以降の最新ウェブ開発](https://www.oreilly.co.jp/books/9784873117836/)
iOS Test Night #9 まとめ

# 概要

自分まとめ用として。 　
二日経つと多分忘却の彼方に飛んでしまうので後でチェックする。  

# XCTest（再）入門 / tobi462さん

Twitter: https://twitter.com/tobi462  


# BetterSpecsに学ぶ Swiftにおける本当にRSpecライクなテストの書き方 / rockname（ロクネム）さん

Twitter: https://twitter.com/_rockname

[BetterSpecsに学ぶ Swiftにおける本当にRSpecライクなテストの書き方](https://speakerdeck.com/rockname/rspec-like-test-in-swift)

## Quick / Nimble

[Quick/Nimble](https://github.com/Quick/Nimble)



# Azure PipelinesでiOSアプリのCI/CDを実現 / nakasho（ナカショ）さん

Twitter: https://twitter.com/nakasho_dev

[Azure PipelinesでiOSアプリのCI/CDを実現](https://www.slideshare.net/shinyanakajima37/azurepipelinesioscicd)


# よく使うテストヘルパーの紹介 / ktanaka117（ダンボータナカ）さん

Twitter: https://twitter.com/ktanaka117

[よく使うテストヘルパーの紹介](https://www.slideshare.net/kenjitanaka58/iostestnight  )


### ダンボーさんの書籍  
[iOSアプリ設計パターン入門](https://peaks.cc/iOS_architecture)

[Swiftで書いておぼえるTDD](https://www.amazon.co.jp/dp/B07JFNVQMK/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)


# 開発者として学ぶソフトウェアテスト / kariad（カリアド）さん

Twitter: https://twitter.com/kariad_uu

[開発者として学ぶソフトウェアテスト](https://speakerdeck.com/kariad/kai-fa-zhe-tositexue-busohutoueatesuto)

# まずはできるところから始めるUnitTestとテストができる実装について / fumiyasac（フミヤサック）さん

Twitter: https://twitter.com/fumiyasac

[まずはできるところから始めるUnitTestとテストができる実装について](https://www.slideshare.net/fumiyasakai37/unittest-125506754)

[過去のスライド](https://www.slideshare.net/fumiyasakai37)

# 参考

[Better Specs { rspec guidelines with ruby }](http://www.betterspecs.org/jp/)

## 備考

このような勉強会の情報のまとめをQiitaで投稿したことありませんのでよくない行為でしたら削除します。

## 蛇足

Swiftでmockを作成する場合のプラグインツール

[SwiftMockGeneratorForXcode](https://github.com/ytama105/SwiftMockGeneratorForXcode)
[Flutter] animationを使って試してみた。その3

今日もお疲れ様です。
Flutterのアニメーション使い。

#以前
1. [[Flutter] animationを使って試してみた。](https://qiita.com/Dreamwalker/items/c195d8ba12e8a55383f1)
2. [[Flutter] animationを使って試してみた。その２](https://qiita.com/Dreamwalker/items/2a99ca6d7206d5195fd4)

# 整理１
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137182/480fc842-ef94-402d-d62f-548ca2d451bc.png)


# 整理２
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137182/e5766a31-aea2-027d-cead-04e318a3517c.png)

# 整理3

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137182/4b7e673b-aa8d-dc99-b144-e5953e169e74.png)
model同士がhas_oneとbelongs_toの関連の時はbuildが使えないので　build_○○○を使う

#UserモデルとProfileモデルで１対１の関連付けを行う。

```profile.rb
class Profile < ApplicationRecord
  belongs_to :user
end
```

```user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :memos
  has_one :profile
end

```

#profiles_controllerにnewアクション、createアクションを定義

ここで大事なのは、1対1の関連の時は***build****ではなく***build_モデル名**の書き方になる

```profiles_controller.rb

  def new
      #@profile = current_user.profile.buildだと動かない。
     @profile = current_user.build_profile
  end
  
  def create
     @profile = current_user.build_profile(profile_params) 
     @profile.assign_attributes(profile_params) #.assign_attributesは変更するだけで保存はしない。フォームから送られてきた値（profile_params）を保存できなかった場合、記入していた文字がそのまま残ってrenderされる
     if @profile.save
       flash[:success] = "名前を登録しました"
       redirect_to root_url
      else
       flash[:danger] = "名前の登録に失敗しました"
       render :edit
     end
  end
```

これで通常通り動きます。
そんなん知らへんやん普通、、
そんなん言うというてや、、


参考
https://qiita.com/SpicyCoffee/items/cfeb728c63f946976cc0
https://gist.github.com/seak0503/7291012e7e99fc8aca80
Vue CLI 3でCSSのSourceMapを有効にする

`vue-cli-service serve` してもデフォルトではCSSのSourceMapが無効になっていたので、有効化してみます。

## 方法

プロジェクトのルートディレクトリに以下のファイルを追加

`vue.config.js`

以下の内容を記述

```js:vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      css: {
        sourceMap: true,
      },
      postcss: {
        sourceMap: true,
      }
    }
  }
}
```

## 確認

**Before**
![スクリーンショット 2018-12-10 21.16.56.png](https://qiita-image-store.s3.amazonaws.com/0/79414/92d9840e-6712-6889-cac2-22bbb26a139f.png)


**After**
![スクリーンショット 2018-12-10 21.18.03.png](https://qiita-image-store.s3.amazonaws.com/0/79414/ce6e0446-a7ec-fde7-3a48-580be176dc92.png)

## 参考

https://cli.vuejs.org/config/#css-sourcemap

以上
AtCoderの無印とbeta版を行き来するUserScript

これは [ AtCoder 関連サービス Advent Calendar 2018](https://adventar.org/calendars/2932) の11日目の記事です。
過去に作った UserScript の atcoder-traffic を紹介します。

この UserScript を使うと、 AtCoder の無印 ( [atcoder.jp](https://atcoder.jp) ) と beta 版 ( [beta.atcoder.jp](https://beta.atcoder.jp) ) を簡単に行き来できるようになります。
##作ったきっかけ
きっかけといっても何か特別なことがあったわけではなく、ただ無印と beta 版の移動が楽にできればいいと思って作りました。
いちいち URL のコンテスト名をコピーして beta 版に移動したり無印に移動したりしていては面倒なので。
え？移動しなくてもいいじゃないか、って？
いやいや、移動しないと不便なことも多いんです。
まず、 beta 版は無印に比べて色々と便利なものが増えています。
順位表で表示項目を色々と設定できたり、コンテストの参加登録を取り消しできたり。
提出画面やコードテストに直接プログラムを入力することもでき、問題画面から直接提出もできます。
また、巷の UserScript は多くが beta 版向けで作られています。
**beta 版最高！！！**
ですが、「 beta 版だけで十分！」とはいきません。
まず、一部の企業コンテストでは beta 版から参加ができません。年齢とかを参加登録時に聞かれるコンテストです。そういう時に無印を使います。
そして、...あれ？これだけ？
しかも、今はそういうコンテストの場合、 beta 版に「旧システムで参加登録」ボタンが付くようになってるはず。
だけど当時はこの「旧システムで参加登録」ボタンとか AtCoder Scores とかいろんなものがまだ beta 版対応してなくて、それでこれを作ったっていう記憶があります。
　でも今はもう対応してるし、じゃあこの UserScript いらないんじゃないの？
え、あ、でも、無印と beta 版を行き来できたら便利じゃない。ほら、コンテスト前の微妙な時間に無印と beta 版をひたすら行き来したりとか、
それにさ、こういうのってあっても損はしないよね、ね、
あと、ええと、あ！そうだ！ [joi.goodbaton.com](https://joi.goodbaton.com) が beta 版に対応してないから、このページから AtCoder の問題ページに飛んだ時でも beta 版を簡単に使えるようにするために使える！
>説明しよう！ [joi.goodbaton.com](https://joi.goodbaton.com) とは、日本情報オリンピック ( 通称JOI ) の過去問を難易度順に探すことができるサイトなのだ！

##機能
 atcoder-traffic の URL → [greasyfork.org/ja/scripts/370878-atcoder-traffic](https://greasyfork.org/ja/scripts/370878-atcoder-traffic)
一番最初のところに少しだけ書きましたが、無印と beta 版を簡単に行き来することができます。

- 上に書いてある URL からインストールします。
- どこでもいいので AtCoder のコンテストページに行きます。( beta 版でもそうでない方でもどちらでもOK )
- 一番上の方にあるコンテスト名をクリックします。( 黒い背景の部分、これ以降はバナーと呼びます　一部のコンテストだとピンク色だったり黒じゃない )
- もともと無印にいたなら beta 版へ、beta 版にいたなら無印に飛べます。

これだけです。あと、JOIに関する機能も一つありますが、それに関しては atcoder-traffic の URL の方の説明を読んでください。ここでは話しません。

##仕組み
正規表現を使って、無印にいるのか beta 版にいるのかを判定します。
正規表現を使って、コンテスト指定の文字列 ( abc114 や code-festival-2018-final-open など ) を抽出します。
そして、バナーのコンテスト名の部分のリンク先を書き換えます。
正規表現様様です。
あとは、無印と beta 版の構造が違うので ( beta 版は問題一覧が .../tasks だけど、無印は .../assignments だったりとか ) 、それも書き換えます。正規表現で。
今のページが問題一覧ページなのか提出ページなのかとかの判定も正規表現でゴリ押してます。
「機能」のところでは言いませんでしたが ( 言い忘れるとかそんなことするはずないじゃないですか ) 、無印の方には、バナーにある開始時刻や終了時刻をクリックすると [timeanddate.com](https://timeanddate.com) に飛べます。 
こんな機能使うはずがないんですが、無印のバナーの部分はデフォルトではコンテスト名と時刻が同じボタンに含まれていて、そのまま beta 版に飛ぶようにすると時刻の部分をクリックしても beta 版の方に飛ぶようになってて、少し気に入らなかったのでボタンを2つに分割して、ついでに時刻の方は [timeanddate.com](https://timeanddate.com) に飛ぶようにした、というわけです。

##最後に
先ほども言った通り、この UserScript を入れたからと言って損はしません。(多分)
元々(多分)あまり意味のないバナーを使ったので機能が減ることはなく、既存のバナーのリンク先を変えただけなので見た目は全く変わりません。
というわけで、是非この UserScript を使ってみてください。

再掲になりますが、atcoder-traffic のリンク先です → [greasyfork.org/ja/scripts/370878-atcoder-traffic](https://greasyfork.org/ja/scripts/370878-atcoder-traffic)
rubyで書いたコードをexe化する方法

ぐぐって得た情報のメモ。

■OCRA
https://qiita.com/grgrjnjn/items/bda60c23366c9716b66a
→一番情報が豊富で有望っぽい。ただし、ファイルサイズは大きくなるとか。

■Neri
https://github.com/nodai2hITC/neri
→検索であまり情報が引っかからない。

■その他
https://qiita.com/aoitaku/items/87ac2714de1c05d114cc
→こんなのもあるらしい。


・背景
gem installコマンドが使えない環境で任意のgemを利用したスクリプトを書く方法として以下の3通りの方法論を考えた。
1.なんとかgem installを使えるようにする
2.gemをlocal installする
3.gemが使える環境(クラウドIDEとか)でコードを書いて、なんとかプログラムだけ持ってくる

1.→プロキシ回避する方法ならあったが、netsh winhttp show proxyで確認してもプロキシ使用してないとのこと。おそらくフィルタリングされている。回避方法が不明。というかVPNなどで無理くり回避するとセキュリティポリシー的にアウトになりそう。

2.→nokogiriのインストールで折れた。gem install一発ですむところが、依存関係にあるファイルをいちいち落としたり、zlibでエラーが発生したり。。。本筋でないところでコスパ悪すぎ。

3.→今のところ本命。OCRAを使って実現できそう。ただし、クラウドIDEで開発するとなると、いちいちexe化してからローカルでテストするとなると面倒くさそう。
追記：Cloud9上でexeファイル作成はできない模様。ぱっと思いつく解決策はEC2インスタンスにlinux入れて仮想環境作ったりするとか・・・？そこまでしたくはない・・・
Metabaseのセグメントとメトリクスを理解する

# 概要
こんにちは、データアナリストの[@k_0120](https://qiita.com/k_0120)です。
BIツール界隈で最近話題になっているMetabase。

今回はMetabase上で利用できる「Segment(セグメント)」と「Metrics(メトリクス)」の機能と利用方法を紹介します。

※Metabaseが何かを知りたい方は、[コチラ](https://qiita.com/ex_SOUL/items/0959bbb7946731e9ae2a#comment-30dfc064704fdf4ae150)の記事をご参照ください。

# Segment(セグメント)
#### Segmentとは？
端的に説明すると、**独自定義のフィルター**です。
メリットとしては、

- 複数人で利用する際に、共通定義でフィルタリングすることができる
- 複雑な条件をまとめてSegment化することで、非アナリストでも容易に希望条件でフィルタリングすることができる

などがあります。

#### Segmentの作成から利用までの流れ
Metabaseのサンプルデータ(Peopleテーブル)を例に説明していきます。

##### 作成方法
1. 「Admin」->「DataModel」の順でページ遷移
2. Segmentを作成したいテーブルを選択
3. 緑枠の「Add a Segment」をクリック
<img width="1267" alt="people.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/9afeb4e2-231e-65e5-e223-3177de4387cd.png">  
4. 「FILTERD BY」に独自定義したい条件を追加  
※今回は「20代かつ参照元がOrganic」というSegmentを作成しました  
※「Preview」をクリックすると、条件にヒットするデータを確認することができます
<img width="1236" alt="segment.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/b5b8f7cf-8a8a-a5db-1280-41027b41e1cd.png"> 
5. Segment名と説明文を入力し「Save changes」をクリック  

これでSegmentの作成は完了です。

##### 利用方法
1. カスタムクエリへアクセス
2. Segmentを利用したいテーブルを選択
3. 「FILTERD BY」をクリック
<img width="1244" alt="segment_custom.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/44c5eddc-597f-6186-d9e5-2a9c4dade749.png">  


すると、先程作成したSegmentがフィルターの一覧に追加されています。
もちろんこのフィルターを選択すれば、Segment作成時に設定した条件が適用されます。


# Metrics(メトリクス)
#### Metricsとは？
端的に説明すると、**独自定義の集計結果**です。
メリットとしては、

- 頻繁に参照する集計結果をMetrics化することで、即座に集計結果を参照することができる
- 集計結果に対して様々なフィルターをかけたい場合、Metricsに対してフィルターをかけるだけで済む  
※例えば、自然検索かつスマートフォンで流入してきたユニークユーザー数に対して、「男性」や「20代」といった様々なフィルターをかけたい場合に、都度都度ユニークユーザー数を定義し集計した上でフィルターをかける、といったことをしなくても済むようになります

#### Metricsの作成から利用までの流れ

##### 作成方法
1. 「Admin」->「DataModel」の順でページ遷移
2. Metricsを作成したいテーブルを選択
3. 緑枠の「Add a Metrics」をクリック  
<img width="1267" alt="peopleのコピー.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/1cfc789b-e187-4714-fee6-4565e52d3d56.png">
4. 「FILTERD BY」に独自集計したいデータの抽出条件を追加  
5. 「VIEW」に集計方法を追加  
※今回は「直近３０日以内に会員登録している」という条件のもと、ユーザー数をカウントしています

これでMetricsの作成は完了です。

##### 利用方法
1. カスタムクエリへアクセス
2. Metricsを利用したいテーブルを選択
3. 「VIEW」をクリック  
<img width="1253" alt="スクリーンショット 2018-12-10 22.09.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/a36adf27-12e4-3fe8-9333-ff2fec8041fb.png">


すると、先程作成したMetricsがビューの一覧に追加されています。
この状態で任意のフィルターをかければ、更にデータを絞った上で集計することもできます。
また、メリットに記載した「即座に集計結果を参照する」ですが、下記の「Metrics」を選択すると、Metrics一覧を表示することができます。
一覧から任意のMetricsを選択すると、カスタムクエリとして集計結果を即座に参照することができます。  
<img width="1259" alt="スクリーンショット 2018-12-10 22.13.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/311026/afa98347-9b96-2ac1-adb0-c348904eeb30.png">


# まとめ
データドリブンな文化を形成する上で、BIツールの導入はとても強力です。
ただし、機能がハイレベルかつ複雑過ぎて宝の持ち腐れになることもしばしば。

データ分析を担当する者としては、ただ分析結果をだすだけではなく、**社内で利用している分析ツールの仕様把握と利用方法を周囲のメンバーへ伝えていくこと**も指名であり責任だと思っています。

大好きなBIツールだからこそ、同じ境遇の方がこの記事を見て、周囲の方へ「Metabase」の良さを広めてくださったら嬉しいです。

# 宣伝
アドベントカレンダー2018にて、[機械学習によるweb広告改善](https://qiita.com/k_0120/items/a39c50c8072f70d1aaf3)というテーマで記事を書いています。
もしよければ、こちらもお読みいただけますと幸いです。
[Fitbit] SubscriptionsAPIを導入するにあたって気をつけたい事 

# はじめに

弊社で運用しているサービス(あすけん)でFitbitのSubscriptionsAPIを利用した時に少々困ったことがあったので記事にしました(´･ω･`)

# FitbitのSubscriptionsAPIとは

```
Fitbitのユーザーデータが変更されたときにサードパーティのアプリケーションに通知するAPIです。
ユーザーのデータを取得するためのポーリングまたはスケジューリングシステムを実装しなくても、アプリケーションはユーザーの最新のデータを保持できまるようになります。
```
![subscriptionAPI-2ffca6a8184619f1be2d8d145439185a.png](https://qiita-image-store.s3.amazonaws.com/0/60503/49ede31e-b78c-fde2-3a35-b12857c9098a.png)
( https://dev.fitbit.com/build/reference/web-api/subscriptions/ より引用 )

# SubscriptionsAPIの流れ

1. ユーザーがFitbitにデータを登録します。
2. Fitbitはタイミングを見計らい、Endpoint URLにアクセスします。
3. EndpointにはTypeで指定したデータがPOSTされます。
4. データをパースし、fitbitからデータを取得します。

# 少々困ったこと

### アクセスが死ぬほど多い

ユーザーデータが更新され、すぐにEndpointが叩かれるため登録人数によってはサーバーへの負荷がエライ事になります。
弊社では、一旦SQS(メッセージキュー)に保管して負荷分散するようにしました(´･ω･`)

### Endpoint URLが一定期間アクセスできなかった場合、SubscriptionsAPIが無効になる

無効に切り替わったぞ通知は送られてきます。
その場合管理画面で有効に変更するだけで良いのですが
停止中のデータの更新方法・復旧手順を考えてから導入した方が良いです(´･ω･`)

### Fitbit側がTLS+SNIに対応していない

CloudFrontを使っている方は要注意。
ELBで対応するなどした方がいいでしょう(´･ω･`)

# まとめ

弊社サービスでは、カロリー計算や運動アドバイスを随時計算するため必要でしたが
サービス内容によってはSubscriptionsAPIを導入する必要も特にはないかと思います。
データを取得するAPIだけの運用でも良いと思うのでご参考になれば幸いです。
バッテリー情報を取得するWebAPPをPythonista3で実装する

端末情報にアクセスするためのツールをPythonistaで実装したくてやってみた。
とはいえ、バッテリー情報を取得するスクリプトはPythonistaにサンプルとして実装されているので、flaskを使ってブラウザから取得できるようにした。

実装は以下の通り。

```python
from objc_util import *
from flask import Flask


app = Flask(__name__)


@app.route('/battery')
def get_battery_info():
    UIDevice = ObjCClass('UIDevice')
    device = UIDevice.currentDevice()
    battery_states = {1: 'unplugged', 2: 'charging', 3: 'full'}
    
    device.setBatteryMonitoringEnabled_(True)
    battery_percent = device.batteryLevel() * 100
    state = device.batteryState()
    state_str = battery_states.get(state, 'unknown')
    device.setBatteryMonitoringEnabled_(False)
    
    return 'Battery level: %0.1f%% (%s)' % (battery_percent, state_str)


if __name__ == '__main__':
    app.run()
```

`objc_util`でObject-Cのライブラリを使うことができる。
これを使って端末情報を取得してバッテリーの残量を取り出している。
あとはPythonista上でアプリを実行し、Safariから`localhost:5000/battery`にアクセスすればバッテリーの残量と充電中かどうかの情報が表示される。

Pythonistaをもっと使いこなしたいので、Object-Cと`objc_util`の使い方を調べておきたい。
deviseでログイン機能実装後に、ログイン後の遷移先を指定する

###application_controller.rbにafter_sign_in_path_for(resource)メソッドを定義すれば解決する様子。

```application_controller.rb

  def after_sign_in_path_for(resource) 
    mypage_path
  end
```

def after_sign_in_path_for(resource)がログイン時に実行されるメソッドで、同様にログイン時に飛んでほしいページを指定します。この場合、mypage_pathとなっております。


自分の場合、新規登録時にはプロフィールを入力させるページに飛ばし、
通常ログインの場合はroot_urlに遷移したかったので以下のようにしました。

```application_controller.rb

  # 新規登録後のリダイレクト先をマイページへ
    def after_sign_in_path_for(resource)
      if current_user
        flash[:notice] = "ログインに成功しました" 
        root_url  #　指定したいパスに変更
      else
        flash[:notice] = "新規登録完了しました。次に名前を入力してください" 
        new_profile_path  #　指定したいパスに変更
      end
    end
```

参考
http://tsumazuki.hatenadiary.jp/entry/2013/08/15/033130
https://qiita.com/salvage0707/items/d3ddc889458ac186e62e#3-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90
firebaseを使って12時間で設計～リリースした話

**「24時間で最初のユーザーを獲得する」**
という企画の一部として12時間で設計～リリースをしろと無理難題を突き付けられたので瞑想を交えつつ作った:eye:
企画の全容は私に当企画を提案してきたディレクターが記事として公開します。公開されましたら当記事を更新しておきます。

先に作ったサービスへのURLを記載しておきますのでお気軽にお試しください。

[東大生と暇つぶし](https://talk-to.jp/)



##作ったもの

#####**東大生(卒も含む)**と話せるチャット的なやつ

- サービス利用者も話し相手(東大生)も**匿名**

- **登録不要**で気軽に使える

- チャットとは言うもののリアルタイムの素早いやり取りは想定しない(掲示板くらいの速度感。最悪メール並み。。。)


話し相手となる東大生は現状２人しか用意できていないが、とりあえずこの体制で。


##渡されたもの

- 画面デザイン(html, css, js)

##使うもの

- Firebase Hosting

- Cloud Firestore

- Cloud Functions

##おおまかな仕組み

だいたいのリクエストは以下の仕組みで動かしている。

①ブラウザからCloud Functionsのfunctionを叩く

 渡された画面デザインとして貰ったjsをちょこちょこいじくり、ajaxでCloud Functionsのfunctionを呼ぶサンプル

```javascript
    $.ajax({
      url: 'https://xxxxx.cloudfunctions.net/xxxxx',
      type: 'get',
      dataType: 'text',
      success: function(result) {
        // cloud functionsからの返却値でごにょごにょ
      }
    });
```

②functionに渡された値を元に、Cloud Firestore内のデータを参照、登録、更新する

　GETパラメーターとして画面入力値などを取得するサンプル

```javascript
exports.xxxxx = functions.https.onRequest((request, response) => {
  var userName = request.query.userName;
  var threadTitle = request.query.threadTitle;
  var comment = request.query.comment;
  .....
  .....
}
```

③function実行後の戻り値を元に画面を操作する

　functionから返ってきた情報を画面に反映させるサンプル

```javascript

    $.ajax({
      url: 'https://xxxxx.cloudfunctions.net/xxxxx',
      type: 'get',
      dataType: 'json',
      data: {"hogeId": id},
      success: function(result) {
        $("#show-thread-title").text(result.threadTitle);
        showChat(result.messages); // messagesを表示する何らかの関数
      }
    });
```

##画面と画面内でのアクション

- トップページ

    - 初期表示(2h消費)  
個人を識別し、ユーザーに紐づくスレッドを表示

    - スレッド作成(4h消費)  
画面入力値をDBに登録し、スレッドページへ遷移
    - スレッドへ移動(2h消費)  
画面で選択したスレッドのスレッドページへ遷移

- スレッドページ

    - 初期表示(2h消費)  
スレッド内のすべてのメッセージを取得して表示
    - コメント追加(4h消費)  
    - 画面入力値をDBに登録し、スレッドページを更新

- 共通

    - トップページへ移動(0h消費)  
アイコンをクリックでトップページへ遷移

##ドメインを独自のものに変更

こちらの記事を参考に、取得した独自ドメインを設定(1h消費)

[Firebaseとムームードメインで独自ドメインでhttps](https://blog.webarata3.link/firebase-mumu)

##まとめ

12時間で作れと言われていたのに15時間かかってしまったこと以外は満足しています。

時間がかかってしまった原因はfirestoreのせい。使ったことないんだもん。

個人情報などをうっかり書き込まないように。こちら側に筒抜けです。

もう一度サービスのURL書いておきます。暇があったら使ってみてください。

[東大生と暇つぶし](https://talk-to.jp/)

二人で回しているため、返信がなかったり遅くても怒りのメールは勘弁して。。。
つかれた。ねむい。サハスラーラ:eye:

【追記】
企画の全容が記事として公開されました。
[こちら](https://tech.yayoi-kk.co.jp/entry/2018/12/14/131613)

あまりにも説明不足かつUIとUXが良くないので改良対応中です。。。。