OmniAICreator/Qiita-1.07M huggingface dataset:
【Slack】Webhook経由での通知でユーザーグループにメンションを飛ばす

# 概要
仕様が変わって、Incoming Webhook経由だと`<@group_name>`でメンション飛ばせなくなったようなので、
slack-apiを使ったIncoming Webhook経由での通知でユーザーグループにメンションを飛ばす方法。

## 参照
[SlackのAPI経由でのメンションの仕様変更(2018/9/12～)](https://qiita.com/gimKondo/items/99ba9b05d14a6b49df68)
[Basic message formatting | slack api](https://api.slack.com/docs/message-formatting)

# 方法
1. ユーザーグループのIDを取得する
2. API経由のメンションをIDに変更する

## 1.ユーザーグループのIDを取得する 
- slack apiの [usergroups.list](https://api.slack.com/methods/usergroups.list/test) からユーザーグループの情報を一覧で取得する
  - もし`token`が未取得の場合は案内が出ているはずなので`token`を取得する
  - Test Methodを押すとjson形式で一覧が取得できる
- メンションを飛ばしたいユーザーグループのIDと名前を調べる
  - IDは`id`と`team_id`がありますが`id`の方です
  - 名前は`name`と`handle`がありますが`name`の方です
  - 公式リファレンスを見ると`handle`でも平気そうな気がするので誰か試してみてください(笑)
![slack_mz.png](https://qiita-image-store.s3.amazonaws.com/0/265229/cac917e2-17a9-2d02-5c84-910e7826fc08.png)

## 2.API経由のメンションをIDに変更する
- Incoming Webhook経由のメンションを下記に変更する
  - `your_team_id`に`id`、`your_group_name`に`name`を入れる

```
<!subteam^your_team_id|your_group_name>
```
- 全員に通知する場合はIDを取得しなくても平気で、それぞれ下記の通り

| Slack上でのメンション方法 | API経由でのメンション方法 |       通知される範囲       |
|:--------------------:|:--------------------:|:-----------------------:|
|     　`@channel` 　     |     `<!channel>`     |    チャンネルのメンバー全員   |
|       `@here`        |       `<!here>`      |     アクティブなメンバー全員    |

## 追記(2020.08.27)
またまた仕様が変わったようです。
(@Ant3_Ng さんありがとうございます)

1. ユーザーグループのIDを取得する
slack apiの usergroups.listを見に行く必要がなくなり、Webでワークスペースを開いてgroupのページを見ると確認できるようです。


2. API経由のメンションをIDに変更する
旧でやると、`@`されるものの通知は来ないようです。

```
旧: <!subteam^your_team_id|your_group_name>
新: <!subteam^your_team_id>
```

詳細：[Formatting text for app surfaces｜Mentioning groups](https://api.slack.com/reference/surfaces/formatting#mentioning-groups)
Bottleを使って書いたWebアプリをHerokuに置くときにrun()を書き換えるのはなんで？

# はじめに
PythonのWebフレームワーク[Bottle](https://bottlepy.org/docs/0.12/index.html, "Bottle公式ページへのリンク")のトップページには以下のサンプルが載っています。

```python:hello_bottle.py
from bottle import route, run, template

@route('/hello/<name>')
def index(name):
    return template('<b>Hello {{name}}</b>!', name=name)

run(host='localhost', port=8080)
```
これを[Heroku](https://jp.heroku.com/home "Heroku公式ページへのリンク")に置くときは、色々と調べると、最終行の`run(host='localhost', port=8080)`を

```python:
run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
```
に書き換えるようです。
これで動作するので問題ないのですが「どうして？」と思ったので調べました。

# `host`はリッスンするインタフェースの指定
一番わかりやすいのは[Deploymentのページ](https://bottlepy.org/docs/0.12/deployment.html "Bottle公式サイトへのリンク")だと思います。
> The bottle run() function, when called without any parameters, starts a local development server on port 8080. You can access and test your application via http://localhost:8080/ if you are on the same host.
>
> To get your application available to the outside world, specify the IP of the interface the server should listen to (e.g. run(host='192.168.0.1')) or let the server listen to all interfaces at once (e.g. run(host='0.0.0.0')). 
> 
> ---
> bottleのrun()関数は、パラメータなしで呼び出されると、8080番ポートでローカルの開発サーバーを起動します。同一ホスト上からなら、http://localhsot:8080/ で、アプリケーションにアクセスしてテストできます。

> アプリケーションを同一ホストだけでなく外部からも利用できるようにするには、サーバがリッスンするインタフェースのIPを指定するか（例えば`run(host = '192.168.0.1')`）、全てのインタフェースをリッスンするかします（`run（host =(0.0.0.0)`。）

`run(host="localhost")`だと`localhost`インタフェースへのリクエストだけをリッスンします。このインタフェースにリクエストを出せるのは同一ホストからだけなので、bottleを起動したホストからしかアクセスできません。
bottleを起動したホストに振られているIPアドレス（例えば`192.168.0.1`）を指定すれば、外部のホストからもアクセスできるようになります。

`0.0.0.0`を指定すれば、全てのインタフェースをリッスンしてくれます。
Herokuに置いたときに振られるIPアドレスは解らないので、全てのインタフェースをリッスンする`0.0.0.0`を指定します。

# Herokuの`port`は動的に決まる
`os.environ`は[公式ページ](https://docs.python.org/3.7/library/os.html#os.environ
 "Python公式ページへのリンク")によると環境変数を表すマップ型オブジェクトを返します。
> os.environ
> A mapping object representing the string environment. 

マップ型オブジェクトなので`get()`が使えます。
`get("PORT", 8080))`で、環境変数`PORT`が存在する場合はその値を、存在しない場合はデフォルト値として`8080`を返します。

Herokuでは、どのポート番号でリッスンするかは動的に決まり、そのポート番号は環境変数`PORT`に格納されます。
そのため`os.environ.get("PORT", 8080))`でポート番号を指定します。

Herokuでは、`PORT`に必ず値が設定されるので、デフォルト値の`8080`を記載する必要はありません。`os.environ.get("PORT")`で十分です。
しかしそうすると、ローカルで試験する際に、必ず`PORT`に値を設定しなければならず面倒です。デフォルト値の`8080`も記載しておいたほうが便利でしょう。

# 残る謎
`heroku config:get PORT`としても、値が返ってこないのはなんで？
HTML5のpattern属性で半角英数記号を指定するにはどう記述したら良いですか？



HTMLやCSSの学習をしています。
正規表現についてはほぼ分かりません。

①ユーザーIDやパスワード入力フォーム半角英数記号のみの入力を処理する場合、type属性は”text”でいいのでしょうか？

②pattern 属性に使う正規表現はほぼ理解できません。自分なりに調べてみたのですが、以下のような記述だと＿アンダーバーや＠マークなどの記号は識別できないのではないかと言われました。
また入力文字数制限は正規表現でも出来るようですが、以下のように自分でもわかるminlength, maxlengthで記述しようと思っていまがこれで大丈夫なのでしょうか？

サンプルとして以下のように記述してみました。
type属性や、「半角英数記号」の入力文字など正しい書き方を教えてください。
よろしくお願いします。


<input type="text" name="username" pattern="^[0-9A-Za-z]+$" minlength="4" maxlength="50">

<input type="password" name="pass" pattern="^[0-9A-Za-z]+$" minlength="3" maxlength="20">
PythonでRubyのp、PHPのvar_dump、JSのconsole.log相当をする

Python初心者なんですが、どうやるのが良いんですかね？
標準の`print` `pprint`はインスタンス変数を表示してくれないのが残念。
サードパーティモジュールもいくつかあるけどGitHubのstar数は多くない。
もしかしてPythonistaはprintデバッグなんてしないんでしょうか？
ほんのちょっと試した中では無名の`ppretty`が一番良かったですが。

- [pprintpp](https://github.com/wolever/pprintpp)
- [beeprint](https://github.com/panyanyany/beeprint)
- [ppretty](https://github.com/symonsoft/ppretty)

下記のコードを使って比較してみました。

```python
import pprint
import pprintpp
import beeprint
import ppretty

class Sage:
    def __init__(self):
        self.x = 9

class Hoge:
    def __init__(self):
        self.a = 123
        self.b = 'moge'
        self.c = [1, 2, {'mm': 3}]
        self.d = Sage()

def pvars(obj):
    try:
        print(vars(obj))
    except:
        print(obj)

def ppvars(obj):
    try:
        pprint.pprint(vars(obj))
    except:
        pprint.pprint(obj)

if __name__ == '__main__':
    objs = [
        Hoge(),
        123,
        'asd',
        None,
    ]

    print('\n### print（標準）')
    for o in objs:
        print(o)

    print('\n### pprint（標準）')
    for o in objs:
        pprint.pprint(o)

    print('\n### pvars（print + vars）')
    for o in objs:
        pvars(o)

    print('\n### ppvars（pprint + vars）')
    for o in objs:
        ppvars(o)

    print('\n### pprintpp（サードパーティ）')
    for o in objs:
        pprintpp.pprint(o)

    print('\n### beeprint（サードパーティ）')
    for o in objs:
        beeprint.pp(o)

    print('\n### ppretty（サードパーティ）')
    for o in objs:
        print(ppretty.ppretty(o))
```

# 比較結果

### print（標準）
```
<__main__.Hoge object at 0x7fd5d931bb38>
123
asd
None
```

### pprint（標準）
```
<__main__.Hoge object at 0x7fd5d931bb38>
123
'asd'
None
```

### pvars（print + vars）
```
{'a': 123, 'b': 'moge', 'c': [1, 2, {'mm': 3}], 'd': <__main__.Sage object at 0x7fd5d931bb70>}
123
asd
None
```

### ppvars（pprint + vars）
```
{'a': 123,
 'b': 'moge',
 'c': [1, 2, {'mm': 3}],
 'd': <__main__.Sage object at 0x7fd5d931bb70>}
123
'asd'
None
```

### pprintpp（サードパーティ）
```
<__main__.Hoge object at 0x7efc722d1b38>
123
'asd'
None
```


### beeprint（サードパーティ）
```
instance(Hoge):
  a: 123,
  b: 'moge',
  c: [
    1,
    2,
    {
      'mm': 3,
    },
  ],
  d: instance(Sage):
    x: 9
123
'asd'
None
```

### ppretty（サードパーティ）
```
__main__.Hoge(
    a = 123, 
    b = 'moge', 
    c = [1, 2, {'mm': 3}], 
    d = __main__.Sage(x = 9)
)
123
'asd'
None
```


# 参考

- [What is a Python equivalent of PHP's var_dump()? - Stack Overflow]( https://stackoverflow.com/questions/383944/what-is-a-python-equivalent-of-phps-var-dump)
- [beeprint: a drop-in replacement for Python's pprint that's actually pretty : Python](https://www.reddit.com/r/Python/comments/52jqe7/beeprint_a_dropin_replacement_for_pythons_pprint/)
FlaskとBottleの容量差

Flaskは元々Bottleをもじったエイプリルフールジョークから発生したものですので、記法もよく似ています。
どっちを使えば良いのかという指針のひとつとして、[速度差を測った人](https://qiita.com/methane/items/bc5b5128bb45dd7627b9)が居ました。
じゃあパッケージの容量はどうかなと調べてみたので[配布用のPython](https://qiita.com/mm_sys/items/1fd3a50a930dac3db299)にインストールするとどれくらい差が出るか調べてみました。

![flask3.png](https://qiita-image-store.s3.amazonaws.com/0/76058/ebd2ca43-f347-b705-99b1-cdb90ea615f0.png)

|フレームワーク|容量|
|:--|:--|
|何もなし|27.6MB|
|Flask|31.3MB|
|Bottle|28.2MB|
|Bottle+Beaker|28.5MB|

※pip のエラー回避のため、PythonNN.zipは解凍してます。

速度差ほど気にしなくて良いようです。

## 参考サイト

> Flaskで書かれたWEBアプリをBottleに書き換えるときの勘所
> http://www.denzow.me/entry/2017/10/17/231204

> wsgi, Bottle, Flask の速度差
> https://qiita.com/methane/items/bc5b5128bb45dd7627b9
Ubuntuにnode入れたときのメモ（2019/02/21）

# Ubuntuにnode入れたときのメモ（2019/02/21）

## Ubuntuにnode入れるときに困った

いつものように「node インストール」で検索して出てくる記事を参考にインストールしていく。

apt-getコマンドでインストール。

しかし、npmが上手く実行できない。

## なんと!!nodejsとnpmのバージョンがめちゃめちゃ古い

node -vで確認してみると、0.10.5とかになっていた。（覚えていない）

現在推奨されているバージョンは10.15.1。とにかくめっちゃ古いことが分かる。

## 公式のインストール方法を確認（修正後）

もっと簡単なのがあったので修正。

https://github.com/nodesource/distributions/blob/master/README.md

```
curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash -
sudo apt-get install -y nodejs
```

これで完了。わしのやってたことって一体…

## 公式のインストール方法を確認（修正前）

以前行った方法。めんどくさいし、sudo npm が効かないっぽい。

以下nodejs公式ページを参考にしてapt-getを使わずにインストールする。

https://nodejs.org/ja/
https://github.com/nodejs/help/wiki/Installation

nodejsのパッケージをリンク先からダウンロードする。推奨バージョンは変わっていくのでnodejs公式ページを見て確認するように。

```
wget https://nodejs.org/dist/v10.15.1/node-v10.15.1-linux-x64.tar.xz
```

バージョンなどを環境変数に入れておく。（この作業いるん？）

```
 VERSION=v10.15.0
 DISTRO=linux-x64
```

展開先のフォルダを作成する。

```
sudo mkdir -p /usr/local/lib/nodejs
```

tarコマンドで圧縮ファイルを展開する。

```
sudo tar -xJvf node-$VERSION-$DISTRO.tar.xz -C /usr/local/lib/nodejs 
```

node,npmをコマンドとして実行できるようにするため、.profileを編集する。viでもなんでも編集できれば大丈夫。

```
vi ~/.profile
```

以下を追記する。

``` ~/.profile
# Nodejs
VERSION=v10.15.0
DISTRO=linux-x64
export PATH=/usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin:$PATH
```
.profileを反映する。

```
. ~/.profile
```

終わり。以下のコマンドで確認。

```
node -v
> v10.15.1
npm version
> { npm: '6.4.1',
>  ares: '1.15.0',
>  cldr: '33.1',
>  http_parser: '2.8.0',
>  icu: '62.1',
>  modules: '64',
>  napi: '3',
>  nghttp2: '1.34.0',
>  node: '10.15.1',
>  openssl: '1.1.0j',
>  tz: '2018e',
>  unicode: '11.0',
>  uv: '1.23.2',
>  v8: '6.8.275.32-node.12',
>  zlib: '1.2.11' }
```
go言語slice利用時のcapacityの変化

メモ。sliceを定義して要素を追加し続ける。
capacityの容量を超えると動的にcap値がスケールする。

```
~/S/g/tourOfGo ❯❯❯ go version
go version go1.11.5 darwin/amd64
~/S/g/tourOfGo ❯❯❯ go run slice9.go
len=0 cap=0 	value=[]
len=1 cap=1 	value=[0]
len=2 cap=2 	value=[0 1]
len=3 cap=4 	value=[0 1 2]
len=4 cap=4 	value=[0 1 2 3]
len=5 cap=8 	value=[0 1 2 3 4]
len=6 cap=8 	value=[0 1 2 3 4 5]
len=7 cap=8 	value=[0 1 2 3 4 5 6]
len=8 cap=8 	value=[0 1 2 3 4 5 6 7]
len=9 cap=16 	value=[0 1 2 3 4 5 6 7 8]
len=10 cap=16 	value=[0 1 2 3 4 5 6 7 8 9]
len=11 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10]
len=12 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10 11]
len=13 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10 11 12]
len=14 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10 11 12 13]
len=15 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
len=16 cap=16 	value=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
len=17 cap=32 	value=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
~/S/g/tourOfGo ❯❯❯
```
【追記】
配列の容量(cap)が1,2,4,8..と変化する事象について、
オライリーのデータ構造とアルゴリズムを読みまして、これは繰り返し二倍化による動的配列実装になっていることがわかりました。

動的な配列を実装する際、配列のスタックが満杯になる都度、配列の要素を1増やす方式(厳密には1増えた新しい配列を用意し、満杯のスタックを全てpushして、新しい要素をpushする方式。)だと、push演算の時間はBig O notationで表すとO(n^2)となります。
(1+2+3+...+nの加算式の結果は(n+1)*n/2で求められ最も高い増加率を示すのはn^2であるためです)

一方で動的配列実装は、配列が満杯になるごとに新しい配列として容量が2倍の配列を用意します。(1,2,4,8,16,32...の要領です。)
この方式の場合push演算の回数は、Big O notationで表すとO(n)となり、上のアイディアよりも演算回数が大幅に削減されます。
配列のスタックが満杯になったときに、新しいスタックに対してpush操作がどれくらい必要か見てみます。満杯になったスタックの容量をnとします
n=1のとき1push演算、n=2のとき2push演算、n=4のとき4push演算、n=8のとき8push演算、、と進みます。
スタックの容量が32に達した時のpush演算の回数は、1+2+4+8+16=31でほぼ2n(32)に等しくなります。2nではnが最も高い増加率を示すので、O(n)となり、アルゴリズムの評価ではこちらの実装の方が計算量が少なく、優れた実装ということになります。
変異の影響をお手軽に確認したい

# 変異の影響をウェブブラウザーを利用してお手軽に確認する
[変異のHGVS表記の相互変換(Ensembl variant_recoder)](https://qiita.com/percipere/items/d884aa2f72b1730f193d)
[変異のHGVS表記の変換(Python hgvs)](https://qiita.com/percipere/items/b82bb05943ea03344d40)
では、コマンドラインを利用して変異の変換の方法について説明した

ただ、手元の一つの変異の影響を調べるのにコマンドを叩くのは辛いとの声も...
もっと、お手軽に知りたいという声ももっともだと思う
そんな時は、www上のサービスを利用する方法がある

**[Ensembl Variant Effect Predictor](https://asia.ensembl.org/Tools/VEP)**
VEPのウェブ版のインターフェイスを利用してアノテーションを行う
<img width="1195" alt="Screen Shot 2019-02-22 at 12.29.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/213053/cf6422f2-ed53-a076-d48b-ddb043b37428.png">

Enter paste data: の部分に変異を入力して"Run!"ボタンを押すと、変異の結果が表示される
(ただし、ちょっと待ち時間がある)

#VEPを利用してもっとお手軽に確認したい
VEPには変異が与える影響を更にお手軽に確認するための仕組みが備わっている
Enter paste data: に変異の情報を入力すると"Run instant VEP for current line"と表示される
<img width="1195" alt="Screen Shot 2019-02-22 at 12.40.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/213053/ad2b6907-585f-7281-0404-52302fca0e39.png">
これをクリックすると<img width="1195" alt="Screen Shot 2019-02-22 at 12.43.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/213053/b771569b-4530-6ef8-1924-7422a25ede1f.png">
こんな風に数秒で変異の影響の概略が得られる

`NM_182763.2:c.688+403C>T`の場合は
<img width="1195" alt="Screen Shot 2019-02-22 at 12.46.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/213053/34fc08b9-d204-92e0-704d-4c205a41c41d.png">

数個の変異の影響をちょっと確認するならVEPの"Run instant VEP for current line"を利用するのがお手軽だろう
ただし、RefseqのIDでのアノテーション表示はこの方法では得られない

Refseq IDでのアノテーションが必要なら
"Transcript database to use:"
- RefSeq transcripts
- Ensembl/GENCODE and RefSeq transcripts
のどちらかを選択して、通常どおり"Run"ボタンを押す

<img width="1195" alt="Screen Shot 2019-02-22 at 12.59.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/213053/4b42fae6-d508-6209-a650-0fb86b3b3269.png">

この場合は、結果が出てくるまでに少し待たなければならない

対象とするヒトゲノムのバージョンによって利用するサイトは異なっている

- [Ensembl Variant Effect Predictor for GRCh38](https://asia.ensembl.org/Tools/VEP)
- [Ensembl Variant Effect Predictor for GRCh37](http://grch37.ensembl.org/Homo_sapiens/Tools/VEP)

今回はここまで:smile:
Clean Architectureで開発中。。。

# はじめに
現在、私が担当しているプロジェクトではClean Architectureを用いて開発しています。
Clean Architectureの記事はたくさんある中で、私は今までMVCでしか開発してこなかった自分のためにも、備忘録として残そうと思い投稿しました。
プロジェクトも半ばではありますが、ひとまずここまで開発してきて感じたことをまとめます。

# 環境
- MacBook Pro (13-inch, 2017)
- macOS Mojave(varsion: 10.14.1)
- Core i5, Memory 16GB
- Xcode(varsion: 10.1)

# Clean Architecture
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3239333336382f37636531666231302d353034652d313665302d383933302d3237386238613766393432642e6a706567.jpeg](https://qiita-image-store.s3.amazonaws.com/0/322831/392b93a1-3005-e2a5-09d8-29c8e369f8e0.jpeg)
Clean Architectureといえば、この図が真っ先に出てくると思います。
これを最初見た時なんの事やらさっぱりでした、、、、、が、以下の記事を参考に見てみると大分理解できました。

[実装クリーンアーキテクチャ](https://qiita.com/nrslib/items/a5f902c4defc83bd46b8)
[Clean Architectureで分からなかったところを整理する](https://qiita.com/gki/items/91386b082c57123f1ba0)



# 構成
構成は以下のようにしています。
![スクリーンショット 2019-02-22 12.31.21.png](https://qiita-image-store.s3.amazonaws.com/0/322831/3c00693d-1989-193a-0088-8febce2d7731.png)
本来ならUseCaseとModelの仲介役としてTranslatorが存在知るのですが、今回プロジェクトとの兼ね合いからTranslatorは使用しませんでした。。。。。。。😅

ざっくりと説明すると、
###Presenter
- ViewとUseCaseの橋渡しを担う

- ViewにModelを渡したり、UseCaseの処理を行う
###View（ViewController）
- ViewのイベントをPresenterへ通知

- Modelに応じて表示させる
###UseCase
- 必要な業務ロジック
###Model
- Viewに必要なValue Object
###DataStore
- 通信やデータ管理を行う
###Entity
- DBのValue Object
###Builder（Provider）
- 各レイヤーに依存性の注入
###Wireframe
- 画面遷移や画面間のイベントを渡す

- Builderを呼ぶ

# まとめ
### メリット 
- レイヤーごとに役割がある程度決まっているため、コードの置き場所に迷うことが少なくなる。

- 上と同じ理由から、途中から要員が参入しても設計自体崩れにくい。

- ある程度命名規則があるため、統一感を持たせやすい。

- テストがしやすい

- 運用・保守がしやすいはず（これからに期待）


###デメリット
- コード・ファイル量が多くなる。

- 冗長なコードが出てきてしまう。

- 導入コストがある。（私がもっと優秀だったなら。。。よかった）

メリットの点で特に感じたのが、途中から要員が参入しても設計自体崩れにくいことですね。
担当のプロジェクトでも途中からメンバーが増員されたのですが、
レイヤーごとに役割が細分化されているので、説明はディレクトリ構成ぐらいで
後はすんなり開発を進められているように見えます。
その方が優秀であることもすんなり進められている要因ではありますが！

デメリットの点では開発当初は、
MVCでの感覚で開発していると、なんで１つの画面にこんなに時間がかかるんだと感じていました。
最近は慣れてきましたが、やはりまだMVCで開発していた時と比べてかかっている気がします。
また、開発が遅いと感じる理由に学習コストもかかっているからだと思います。
初めてのClean Architectureだったので、
思想やそれを踏まえての構成であったりと理解するのにどうしても時間がかかっている印象です。（現在進行形）

メリット、デメリットまとめてみました。その結果として感じたことは、
Clean Architectureをどのプロジェクトにも絶対取り入れた方がいいとは思ってはおらず、
プロジェクトの規模や開発メンバーに合うものを取り入れていくことがベターだと思います。
ただ、プロジェクトの規模が大きいのであればClean Architectureオススメです。という一個人の感想で締めたいと思います。

##参考
[実装クリーンアーキテクチャ](https://qiita.com/nrslib/items/a5f902c4defc83bd46b8)
[Clean Architectureで分からなかったところを整理する](https://qiita.com/gki/items/91386b082c57123f1ba0)
https://speakerdeck.com/koutalou/ios-clean-architecture-falsesusume?slide=11
[まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて](https://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc)
全国民が必要としている都道府県コード

## 探してもなかったので

### Python
```
PREFECTURE_CODE_DICT = {
    '01': '北海道',
    '02': '青森県',
    '03': '岩手県',
    '04': '宮城県',
    '05': '秋田県',
    '06': '山形県',
    '07': '福島県',
    '08': '茨城県',
    '09': '栃木県',
    '10': '群馬県',
    '11': '埼玉県',
    '12': '千葉県',
    '13': '東京都',
    '14': '神奈川県',
    '15': '新潟県',
    '16': '富山県',
    '17': '石川県',
    '18': '福井県',
    '19': '山梨県',
    '20': '長野県',
    '21': '岐阜県',
    '22': '静岡県',
    '23': '愛知県',
    '24': '三重県',
    '25': '滋賀県',
    '26': '京都府',
    '27': '大阪府',
    '28': '兵庫県',
    '29': '奈良県',
    '30': '和歌山県',
    '31': '鳥取県',
    '32': '島根県',
    '33': '岡山県',
    '34': '広島県',
    '35': '山口県',
    '36': '徳島県',
    '37': '香川県',
    '38': '愛媛県',
    '39': '高知県',
    '40': '福岡県',
    '41': '佐賀県',
    '42': '長崎県',
    '43': '熊本県',
    '44': '大分県',
    '45': '宮崎県',
    '46': '鹿児島県',
    '47': '沖縄県'
}
```
Nitroハイパーバイザーを使用したEC2インスタンスに移行するときの注意点

簡単なようでハマったのでメモ。

## 前提
ローカル環境にaws-cliインストール済み。
ubuntu18環境。osアップデート済み。
以下はt2.smallからt3.smallに移行する例。

## ENAの状態確認
```bash:instance
$ ethtool -i eth0
driver: vif
version: 
firmware-version: 
expansion-rom-version: 
bus-info: vif-0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
```
driver: vifだと無効。driver: enaだと有効。

```bash:local
$ aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].EnaSupport"
```
Trueが返ってくれば有効。

## fstab設定確認
fstabでルートデバイス以外のボリュームをマウントしている場合。
t3にするとデバイスファイル名が変わるので、fstabで指定していると、マウントに失敗してOSのbootで失敗する。
fstabにnofailが入っていなければ入れておく。
```text:/etc/fstab
/dev/xvdf       /data   xfs    defaults,nofail        0       0
```


## ENA有効化
有効化はaws-cliからのみ可能。

```bash:local
インスタンス停止
$ aws ec2 stop-instances --instance-ids <instance-id>

ENA有効化
$ aws ec2 modify-instance-attribute --instance-id <instance-id> --ena-support

EBS最適化
$ aws ec2 modify-instance-attribute --instance-id <instance-id> --ebs-optimized

インスタンスタイプ変更
$ aws ec2 modify-instance-attribute --instance-id <instance-id> --instance-type t3.small

インスタンス起動
$ aws ec2 start-instances --instance-ids <instance-id>
```

T2/T3 無制限設定は任意。(t3はデフォルトON)

```bash:local
$ aws ec2 modify-instance-credit-specification --instance-credit-specification "InstanceId=<instance-id>,CpuCredits=unlimited"
```

## fstab設定
デバイスファイル名を確認。

```bash:instance
$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 17.9M  1 loop /snap/amazon-ssm-agent/1068
loop1         7:1    0 87.9M  1 loop /snap/core/5328
loop2         7:2    0   18M  1 loop /snap/amazon-ssm-agent/930
loop3         7:3    0   91M  1 loop /snap/core/6405
loop4         7:4    0 12.7M  1 loop /snap/amazon-ssm-agent/495
nvme0n1     259:0    0   30G  0 disk 
nvme1n1     259:1    0    8G  0 disk 
└─nvme1n1p1 259:2    0    8G  0 part /
```

元々xvdfであったのがnvme0n1に変わっていた。

デバイスのUUIDを確認。

```bash:instance
$ blkid /dev/nvme0n1
/dev/nvme0n1: UUID="xxxxx" TYPE="xfs"
```

fstabを変更する。
デバイスファイル名は固定ではない。ここは要注意。
なのでUUIDを指定する。

```text:/etc/fstab
UUID="xxxxx"       /data   xfs    defaults,nofail        0       0
```

インスタンス停止→起動で、マウントされて正常に起動される。

ENAが有効になっている。

```bash:instance
$ ethtool -i eth0
driver: ena
version: 2.0.2K
firmware-version: 
expansion-rom-version: 
bus-info: 0000:00:05.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
```

##参考
https://qiita.com/m1104m/items/cecaa43c17ab54ecea67
https://blog.adachin.me/archives/7736
https://ryuzoji.com/archives/1041
https://qiita.com/isobecky74/items/4dddb4407ac7e5f2c45a
自動生成したHTMLがLinuxで文字化けしたときの対処法

## 現象
Windows では意図通りに生成できた HTML(UTF-8) がLinux (Ubuntu、CentOS) では文字化けする。

### 再現条件
各 OS で当初の使用ブラウザは以下の通り。

Windows 10 では Chrome を利用している。
こちらは問題なく意図した表示がされる HTML を吐き出す。

Ubuntu 18.04 LTS では Chromium をデフォルトに設定している。
Ubuntu 特有の症状か確認するため、Windows 10 上の仮想マシンへ CentOS 7 をインストールした。
ペンギンたちは両者とも HTML の表示は文字化けしている。

ただし、Firefox では問題なく意図した通りに表示された。
狐につままれたような気持ちだわ。偉いぞ狐。

## 解決に至るまで

### ファイルエンコードがおかしい？
つまらないケアレスミスをしていないか。
保存時にエンコードを Shift_JIS あたりにしていないか。

- 当然 UTF-8 にしてますよねー。

### 生成時のファイルエンコードがおかしい？
他の言語が同じ場面でどうなるか分からないので、今回はあくまで Python 3.7.0 での話。
違う言語で開発していれば困らないのだろうか。
しかし別章で示すけど、JavaScript と PHP（2014年なので ES2015 や PHP 7 以前の時代だろうか）も同じ現象があったみたい？

ファイル生成時にやらかしているかもしれない。
ファイルの読み書き時にエンコードを指定できるので、保存時に何かやらかしている可能性に賭けて一応エンコードを弄る。

- そもそも Python 3 系はデフォルトで UTF-8 だよなぁ。

### Linux だと入出力が変わる？
[`sys`や`io` を import して標準入出力を弄ろうとしたり](https://qiita.com/methane/items/6e294ef5a1fad4afa843)、[localeの設定を変えたり](https://www.server-world.info/query?os=Ubuntu_18.04&p=locale)。

```確認.
$ echo $LANG
ja_JP.UTF-8

```
変更してもどうにもならないっすね……。

様々なサイトを読んでいると、Linux で皆さん同じようなことで苦労しておられるようで。
どうにかしてくれ。


## 解決策
[header に metaタグ を付けよう（戒め）](https://stackoverflow.com/questions/21733144/utf-8-text-is-being-garbled)

生成ファイルをブラウザ上で確認したいなら、一行目に `<meta charset="UTF-8">` を書くだけで読めますね。
HTML4 なら`<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">` で指定していたみたいね。
~~これに気づくまでに3時間……。~~
自分の場合は生成ファイルをテンプレートエンジンに埋め込むため、テンプレートエンジンが UTF-8 に設定されていれば期待通りの表示がされてくれると祈祷している。

祈りが通じなかったら追記します。
MacBook Pro 2018にUbuntuがインストールできない話

## 概要
- MacBook 2018, MacBookPro2018などにはUbuntuなどがインストールできません。
- 正確には、[Apple T2 security chip](https://support.apple.com/ja-jp/HT208862)を搭載しているモデルには、Ubuntuなどを含むLinuxをインストールすることができません。

## 参考
- https://www.omgubuntu.co.uk/2018/11/apple-t2-chip-cant-boot-linux
    - セキュリティを緩めることで、USBなどからOSを起動できることが説明されている。
    - 起動することはできるが、後述のようにインストールができない。
- https://askubuntu.com/questions/1052373/install-ubuntu-bionic-18-04-on-macbook-pro-2018
    - Getting the internal trackpad and keyboard to work with the 2018 Macbook pro is the least of your concern really. There are no drivers for the Apple SSD controller yet. So regardless of that fact, it won't let you install anything...
    - There are no drivers for the Apple SSD controller yet.
    - いまのところ、MacBook Pro2018にUbuntuをインストールできた人は観測できていない。
jquery.MultiFile のエラーメッセージを日本語化

自分用。せっかく書いたはいいが、没になったので。
公式サイトも消えて、後継サイト？のドキュメントに書いている内容は
ソースコードの記述と食い違っているなど色々苦労しました。

```js:
/**
 * jquery.MultiFile
 *
 * @see https://github.com/fyneworks/multifile
 * @see http://lampspw.wallonie.be/dgo4/tinymvc/myfiles/plugins/multifile-2.2.1/docs.html
 */
function initMultiFile()
{
    var target, acceptExtention, maxFileUploads, maxUploadFileSize, postMaxSize, previewCssStyle;

    target = '.multi-files';
    acceptExtention = 'jpg|png|gif';
    maxFileUploads = 20;
    maxUploadFileSize = 256; // KB
    postMaxSize = maxUploadFileSize * maxFileUploads; // KB
    previewCssStyle = 'max-height:100px; max-width:100px;';

    $(target).MultiFile({
      accept: acceptExtention,
      max: maxFileUploads,
      maxfile: maxUploadFileSize,
      maxsize: postMaxSize,
      preview: true,
      previewCss: previewCssStyle,
      STRING: {
          remove: 'x',
          denied: '許可されていない拡張子です：$ext',
          file: '$file', // span.MultiFile-title text
          selected: '$file', // span.MultiFile-label title attribute
          duplicate: 'アップロード済みのファイルです：$file',
          toomuch: '同時アップロード可能ファイルサイズの上限に到達しました\n (最大サイズ：$size)',
          toomany: '同時アップロード可能ファイル数の上限に到達しました\n (最大数：$max)',
          toobig: 'ファイルサイズが大きすぎます：$file\n (最大サイズ：$size)'
      }
    });
}
```
jQueryを使わずにDjangoでAjax！

こんちは。

ここ数年で、フロントエンド界隈には反jQueryな方々が増えてることを知りました。
私はそこまでこだわりはないんですけどね、せっかくなら動作は軽いほうがいいし、素のJavascriptだけでAjaxができたらいいよねってことで。

ただ、Djangoの公式にもjQueryの例しか載ってないからチョット苦労しました…
とりあえず形にはなったので、忘れないように書いときます。

#方法
DjangoにおけるAjaxは、GETは簡単なのですが、POSTについてはheaderに*csrftoken*をくっつけないと怒られてしまうのです。
このトークンはCookieから取り出さないといけないので、公式の通りに[js-cookie](https://github.com/js-cookie/js-cookie)を導入しといてください。
###1. POST
```.js
// 送信データを用意します
let data = new FormData();
data.append('キー1', '内容');
data.append('キー2', '内容');
.
.
.

const request = new XMLHttpRequest();

request.open('POST', '送信先のurl');
request.setRequestHeader("X-CSRFToken", csrftoken); // csrftokenをくっつけます
request.onreadystatechange = function () {
   if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
      // 正常に受信完了した時の処理
      const d = this.response; // これで帰ってきたデータを取り出せます
   }
};
request.send(data); // この時点で送信されます
```

###2. GET
```.js
const request = new XMLHttpRequest();

request.open('GET', '送信先のurl?param1=data1&param2=data2...');
request.onload = function () {
   // 正常に受信完了した時の処理
   const d = this.response; // これで帰ってきたデータを取り出せます
}
request.send(data); // この時点で送信されます
```

以上です。以上のはずです…

ミスがあったら教えてくださいな。
【連載】ジャンプ＆ランゲームを作ろう(4) ボールをジャンプ＆カメラをボール追従に

# はじめに

こちらのQiitaは勝手連載「ジャンプ＆ランゲームを作ろう」になります。
初回の記事はこちらです。
[【連載】ジャンプ＆ランゲームを作ろう(1) プロジェクト作成](https://qiita.com/motoyasu-yamada/items/3fcc164cae23537b5f1a)
※お断り※ 毎日お昼休みに15分程度で執筆していおり細切れになりましてすみません


# 今日の内容

今日はボールを表示させます。画面をタップするとボールは上にジャンプし自然に落下します。
また、カメラはボールに追従します。ボールの真横に常に追従するのではなく、追っかける実装にしました。

# 今回のソースコード

https://github.com/liberapp-inc/h5g-qiita-jump-and-run/tree/f5ee116ece4f5ea64d82275599c88e692c6253df

コミット内容：
https://github.com/liberapp-inc/h5g-qiita-jump-and-run/commit/f5ee116ece4f5ea64d82275599c88e692c6253df

# 解説

フレームレートを30から60にあげます

```diff:index.html
         data-entry-class="Main"
         data-orientation="portrait"
         data-scale-mode="fixedWidth"
-         data-frame-rate="30"
+         data-frame-rate="60"
         data-content-width="640"
         data-content-height="1136"
         data-multi-fingered="2"
```

## タップイベントの処理

タッチ開始イベント`egret.TouchEvent.TOUCH_BEGIN`のハンドラー`this.tap`を登録します。

ハンドラーでは、ジャンプ処理などを行わずに、`tapped`変数をtrueにして、タップフラグを立てるだけです。

```diff:Main.ts
    private async runGame() {
:
+        this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.tap, this);
    }
:
+    private tapped: boolean;
:
+    private tap(e: egret.TouchEvent) {
+        this.tapped = true;
+    }
```

## ボールの初期化

ボールの底面の判定が重要なので、ボールの底面をボールのY座標にします。

```ts:Main.ts
    private createBall() {
        this.ball = new egret.Shape();
        this.ball.x = 0;
        this.ball.y = 0;
        {
            const g = this.ball.graphics;
            g.beginFill(0xcccc00);
            g.drawCircle(0, -16, 16);
            g.endFill();
        }
        this.world.addChild(this.ball);
    }
```

## ボールの更新処理

まずボールがタップされたら、垂直方向の速度ballVyを画面上方向に加速させます。

またボールが床についていない(座標が0未満)ならボールに重力を働かせます

そして、速度(ballVx,ballVy)に応じてボールの位置を移動させます。

ボールが床にめりこまないように調整をします。

```ts:Main.ts
    private updateBall() {
        if (this.tapped) {
            this.ballVy -= 3;
            this.tapped = false;
        }        
        if (this.ball.y < 0) {
            this.ballVy += 0.1;
        }        
        this.ball.x += this.ballVx;
        this.ball.y += this.ballVy;
        if (0 <= this.ball.y) {
            this.ballVy = 0;
            this.ball.y = 0;
        }
    }
```

# まとめ
今日は時間がないので以上です。
正規表現の覚え書き（随時更新）

## 正規表現覚え書き
正規表現の覚え書き。自分用メモです。
ハマったものだけ随時更新。
主にサクラエディタで動作確認しています。

- 最初に出てきた数値文字列の前にタブを挿入したい。

``` 
*検索文字列*
(^.*?)([0-9０-９])
*置換文字列*
\1\t\2
```

（解説）
()で囲んだ文字列でグループを形成し、置換文字列の\1、\2でグループを指定。
あとは2つのグループの間に正規表現でタブを挿入。

- 1行に2つ以上タブがある行をピックアップしたい

```
^.*\t.*\t.*$
```
（解説）
特になし。

- 最後「\（円マーク）」だけ置換したい

```
\\(?=[^\\]*$)
```
（解説）
特になし。
GitHubにSSHで接続する

SSHのキーを作る。

```
ssh-keygen -t rsa
```

https://github.com/settings/ssh で公開鍵をGitHubにアップロードする。

```
ssh -T git@github.com
```
で接続できるかを確かめる。`~/.ssh/config` に設定を書く：

```
Host github github.com
  HostName github.com
  User git
  IdentityFile "/Users/a/.ssh/id_rsa"
```
`~/.gitconfig` に以下の設定を追加する。

```
[url "github:"]
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:
```
もしくは以下をリポジトリのディレクトリ内で行う。

```
git remote set-url origin git@github.com:[ユーザ名]/[リポジトリ名].git
```
TableViewのreloadData()後レイアウトがズレる(カクカク)改善メモ

#はじめに
・tableViewをページングする際にreloadData()を行うとtableViewがカクカクする現象
・tableViewの`estimatedHeightForRowAt:`の設定でハマっていいたのでメモ
・ページングした時にtableViewHeightの見積もりが合わない,または更新されない場合に発生
#確認すること
tableViewの見積もりにより、正確な高さを取得できなくて（間に合わず）発生するので`estimatedHeightForRowAt`を設定。
固定cellなので`return UITableView.automaticDimension`で自動で高さを見積もればいいと思っていましたが、tableViewのindexPathでcellの高さを計算した方がtableViewの動きがよくなりました。また、`estimatedHeightForRowAt`は更新の時に逐一呼ばれるので、`UITableView.automaticDimension`だとtableViewCellの見積もりを再計算しなおすので効率が悪くカクカクの原因になってしまう。とういうことで記述

```swift:tableView.swift
var cellHeight: [IndexPath: CGFloat] = [:]

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        guard let cellHeight = self.cellHeight[indexPath] else {
            //取得できなかった場合に自動計算
            return UITableView.automaticDimension
        }
        return height
    }
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if self.cellHeightList.keys.contains(indexPath) != true {
            self.cellHeightList[indexPath] = cell.frame.height
        }
    }
```

#最後に
tableViewの更新などを行う場合は、`cellHeight`辞書のクリアを忘れずに行わないとcellの高さがうまくキャッシュされない。
Windowsマシンをchocolateyでセットアップする手順（いまさら）


普段はWindowsでエクセルとパワポとメールぐらいしかしなかったのですが
会社で開発用に新品のSurfaceを購入してもらったこともあり、
せっかくなのでchocolateyとConEmuを使ったセットアップを簡単にまとめて記事にしました。

* 動作確認環境: Windows10 64bit

## chocolatey install

chocolateyのインストールになります。

https://chocolatey.org/docs/installation

PowerShellを起動してchocolateyをインストールします。

```
C:\> @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```

chocolateyをインストールしたらアップグレードしておきます。

```
choco upgrade chocolatey
```

### 基本コマンド

これくらい覚えておけばなんとかなりそう。

| コマンド | 内容 |
|:-----|:-----|
| choco install [package name]| パッケージのインストール|
| choco list | パッケージの一覧表示 |
| choco list [package name] | パッケージの検索|
| choco list -localonly | インストール済みパッケージの一覧表示 |
| choco update all | インストール済みのパッケージを全てアップデート |
| choco uninstall [package name] | パッケージのアンインストール |



## chocolatyを使ったパッケージのインストール

パッケージ一覧は以下を参照してください。

https://chocolatey.org/packages

以下は、私がとりあえず開発に必要だったパッケージをインストールしています。

### java8

jvmアプリ開発のためのパッケージ

```
choco install jdk8
```

### JetBrains IntelliJ IDEA (Community Edition)

InteliJ IDEA

```
choco install intellijidea-community
```

### msys2

Unixライクにコマンドを使うためのパッケージ

```
choco install msys2
```

### jq

jsonを便利に扱うためのパッケージ

```
choco install jq
```

### Git

```
choco install git
```

### MariaDB

```
choco install mariadb
```

### ConEmu

ターミナル

```
choco install ConEmu
```

## ConEmuの設定

ConEmuを上記でインストールしたので、msys2と組み合わせてUNIXライクなシェル環境を構築する手順を記載しています。

![ConEmuSetting.png](https://qiita-image-store.s3.amazonaws.com/0/203061/d49b5fdc-bc62-eda7-81bd-f6877adebf1e.png)

④のコマンドは以下をコピペして入力してください。

```
set CHERE_INVOKING=1 & set MSYS2_PATH_TYPE=inherit & %ConEmuDrive%\tools\msys64\usr\bin\bash.exe --login -i -new_console:C:"%ConEmuDrive%\msys64\msys2.ico"
```
Now for GitHubで自動デプロイする

はじめまして。
仕事では未だにSubversionが現役おじさんです。
GitHubは勉強中です。

# 概要

[NOW](https://zeit.co/now)良いですよね。
軽い気持ちでサーバレスにデプロイできます。

`now`コマンドを打たなくても、
GitHubにPushすると自動でデプロイする方法がありました。
便利ですね。

# 環境構築

## モジュールの準備

- ソース用のフォルダを用意します。

```powershell
mkdir now-autodeploy
cd now-autodeploy
```

- `npm`でポチポチやっていきます。

```powershell
npm init -y
npm i -g now
npm i express
```

- nowの設定を作ります。
- `alias`は好きなエイリアスを付けましょう。

```json:now.json
{
  "version": 2,
  "name": "now-autodeploy",
  "builds": [{ "src": "index.js", "use": "@now/node" }],
  "alias": "now-autodeploy"
}
```

## 実装
- お試しなので、`express`を使います。

```javascript:index.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello World');
});

module.exports = app;
```

- .gitignoreも作っておきましょう。

```:.gitignore
node_modules
```

## デプロイ

- nowコマンドを打つだけ。初回はログインを求められます。

```powershell
now
```

- エイリアスに反映したい場合、↓も追加で打ちましょう。

```powershell
now alias
```

## 結果確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/365084/9239664f-c1be-0ea3-3c5e-d7544ca9ab7c.png)

良いですね。

# 自動デプロイ設定

## リポジトリ作成

- GitHubのリポジトリを作成します。
- 今回は`now-autodeploy`リポジトリを作っておきました。

## Now for GitHubの設定

https://zeit.co/login

- さきほど登録したユーザーか、GitHubのアカウントでログインします。

- :gear:をポチって、設定画面を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/365084/5611c439-971c-13e3-fbb9-0b19f75b8b7c.png)

- `INSTALL NOW FOR GITHUB`ボタンをポチりましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/365084/7b0615b0-6bb3-bec3-80f7-bc0c197c1742.png)

- 全てのリポジトリか、選択したリポジトリ（複数可）できます。
    - 今回は`now-autodeploy`リポジトリのみを対象にします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/365084/e24d8e45-923a-a013-b5f2-0100659a0337.png)

- 画面下部の`Install`ボタンをポチれば、設定は終了です。簡単ですね。

## ソース修正
- GitHubに登録する前に、ソースコードを修正しておきます。

```javascript:index.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
-  res.send('Hello World');
+  res.send('Hello World (auto deploy)');
});

module.exports = app;
```

## 共有リポジトリ反映

```powershell
git init
git remote add origin https://github.com/orbit0801/now-autodeploy.git
git add --all
git commit -m "first commit."
git push -u origin master
```

## 結果確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/365084/b68b0274-c67d-76f6-daf8-0ac83bf6e027.png)

`now`コマンドを打たなくてもデプロイされました。良かったですね。
自動でエイリアスまで反映してくれます。ありがたいですね。

- 少し時間が掛かります。
- 終わらない場合、ダッシュボードからデプロイ状況を確認しましょう。

# now.jsonの追加設定

https://zeit.co/docs/v2/integrations/now-for-github/#configuration

- 色々追加で設定できるようです。良いですね。

# ソースコード

https://github.com/orbit0801/now-autodeploy
gemを使うときに変なエラーが出たら (ERROR:  While executing gem ... (TypeError)     incompatible marshal file format (can't be read)     format version 4.8 required; 60.33 given)

# 下記のようなエラーが出たとき
```
gem install bundler
ERROR:  While executing gem ... (TypeError)
    incompatible marshal file format (can't be read)
	format version 4.8 required; 60.33 given
```

```
gem update --system
ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)
    server did not return a valid file (http://gems.rubyforge.org/specs.4.8.gz)
```

# 解決法
sourcesが古いからだった

```
gem env
RubyGems Environment:
...
  - REMOTE SOURCES:
     - http://gems.rubyforge.org/
     - http://gems.github.com
...
```

なので、

```
# 下記2つのソースを削除
gem sources -r http://gems.rubyforge.org/
gem sources -r http://gems.github.com

# 追加
gem sources -a https://rubygems.org/

# 確認
gem sources -l                       
*** CURRENT SOURCES ***

https://rubygems.org/
```
で解決

ここでも役立っていた😁
https://github.com/rubygems/rubygems/issues/1589#issuecomment-466381653
Dockerメモ

# Docker
- コンテナ型仮想化アプリケーション
 - ホストOSのカーネルを利用して隔離された環境を作成すること
 - その為軽量
- Dockerコンテナの操作はDockerエンジンを介して実行される
- Dockerコマンドにより指示を出す
- Dockerイメージに必要なものはまとまっているので、環境依存度が低い
- ホストOSの1プロセスとして動作する
  - セキュリティの面において問題がある


### ホスト型仮想化
- ホストOS上に仮想化ソフトウェアを動作させ、その上にゲストOSを構築する
- VMwareなど
- 重い

### ハイパーバイザ型仮想化
- ホストOS上にハイパーバイザーと呼ばれる仮想化ソフトウェアを動作させ、その上にゲストOSを構築する
- 起動が遅い、重い


 # Dockerイメージ
- コンテナ実行に必要なファイルをまとめたファイルシステム
- 複数のレイヤーで構成されている
- 読み取り専用
- コンテナが起動すると読み書き可能なコンテナレイヤーが起動する

## コマンド
- docker run：以下の複合
  - docker pull:イメージを取得する、タグを指定しないとlatestが必ず指定されるが、実際にはlatest以外が最新版というときには、古いバージョンを落とすことがある。
  - docker create:イメージを作成する
     - -it:
  - docker start:イメージを起動する

- docker images：環境上に存在するimage一覧を表示する
- docker ps:プロセスを表示する
- docker pause:ポーズ状態にする
- docker unpause:ポーズ状態を解除する
- docker tag:タグを変更する
- docker inspect:イメージの詳細を確認する
- dcoker rmi:イメージの削除
- docker cp:ホストマシンとdockerイメージの間でファイルをコピーする


- docker login:Docker Hubへログイン
- docker login quay.in:quay.inへログイン

- docker push:イメージをプッシュ
- docker push dockerid/イメージ名:タグ名

- docker exec -it:コンテナのシェルに接続する
- docker attach:コンテナのシェルに接続する
  - Ctrl+P+Q or "exit" 

- docker build　:イメージビルド
  - -t XX .:名前をXXとする　
  - --no-cache:キャッシュを使用しない
  - 再度同じdockerfileからイメージビルドした場合、コマンドに変更がある行以降のみ実行される（キャッシュが使用される）
そのため

- docker commit

## Dockerファイル
- FROM 元になるイメージを作成する際に指定する命令
- RUN bashコマンドを実行する？
- CND 
- COPY 指定したファイルをホストマシンからコンテナへorコンテナからホストマシンへコピーする
- ADD COPY+tarでアーカイブされたファイルやURLからコピーする機能

## Dockerステータス
- created
- running
- exited
- removing
- paused
- restarting
- dead
【React Native】Build Successだがbundle error

## 背景
- Build Success
- Metro Bundler bundle error

## 試すこと
1.  `watchman watch-del-all`
2. `rm -rf $TMPDIR/react-native-packager-cache-* && rm -rf $TMPDIR/metro-bundler-cache-* && rm -rf $TMPDIR/haste-map-react-native-packager-*`

## 確認
```
$ react-native start --reset-cache
```
こんなのがでてきたら

```shell
 ERROR  Metro Bundler can't listen on port 8081
```

ポートが埋まってるか確認

```shell
$ lsof -i:8081
```

でてきたPIDをことごとくkillして

```
$ kill 72505
```

もう一回確認

```
$ react-native start --reset-cache
```

エラー出なかったら起動成功する可能性大！
POSIX や bash でコマンドが存在するか確認する関数（which でない）

> コマンドのインストール前にインストール済みか確認したい。できれば POSIX 互換にしたい。

インストーラーのスクリプトを書く際に、事前に**必須コマンドが導入されているかチェックしたかった**のです。

一般的に `which` コマンドが使われますが、**[POSIX 準拠コマンド一覧](https://pubs.opengroup.org/onlinepubs/9699919799/idx/iw.html)には `which` がありません**。

「`which` より確実なのあったなぁ、なんだっけかなぁ」と、[ここ１年で作成／更新された Qiita 記事を「`bash` `関数` `コマンド` `存在` `確認`」でググって](https://www.google.com/search?q=site:qiita.com+bash+%E9%96%A2%E6%95%B0+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89+%E5%AD%98%E5%9C%A8+%E7%A2%BA%E8%AA%8D&tbs=qdr:y)も（タイトルから）ピンポイントでわかる情報がみつかりませんでした。いや、[１年以上前の未更新記事ならたくさんある](https://www.google.com/search?q=site:qiita.com+bash+%E9%96%A2%E6%95%B0+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89+%E5%AD%98%E5%9C%A8+%E7%A2%BA%E8%AA%8D)のですが、自分のググラビリティとして。

### TL;DR

> which でなければ type コマンドです

### TS;DR

```bash:関数
#!/usr/bin/env bash

function existsCmd () {
    type -a $1 > /dev/null 2>&1
}
```
```bash:用途
if ! existsCmd bash; then
    echo 'bash does not exist'
    exit $LINENO
fi
echo 'bash exists'

if existsCmd hoge; then
    echo 'hoge exists'
    exit $LINENO
fi
echo 'hoge does not exist'

if ! existsCmd fuga; then
    echo 'fuga does not exist'
    exit $LINENO
fi
echo 'fuga exists'
```
```shell-session:実行結果
bash exists
hoge does not exist
fuga does not exist
```

- 動作確認環境：macOS Mojave（OSX 10.14.3）, bash 3.2.57
- [オンラインで動作確認する](https://paiza.io/projects/aop-b92unl6-4I3BX6Cy_w) @ paiza.IO

## 参考文献＆あわせて読みたい

- 「[コマンドが存在するかしないかを判定して, 条件分岐する構文のまとめ](https://qiita.com/skkzsh/items/d63861293fd6bde1b0d8)」@ Qiita
- 「[シェルスクリプトで関数を利用する](https://qiita.com/kaw/items/034bc4221c4526fe8866)」@ Qiita
- 「[Bashでコマンドの存在チェックはwhichよりhashの方が良いかも→いやtypeが最強](https://qiita.com/kawaz/items/1b61ee2dd4d1acc7cc94)」@ Qiita
私も画像が投稿できるWebアプリを作りたい。その1

#0.準備
CRUD機能の備わっている
Webアプリケーションを用意してもらう必要があります。

progateのRuby on Rails5
レッスンⅠからⅣを
やってから戻ってきてください。

よろしくお願いします。

#1.ゴールは？

画像アップロード機能の実装！！
（「Faceb○○k」や「I○stagram」みたいなのを作りたい！！）
#2.実装
```
$ rails db:create
　　　　①
```
①画像の情報を保存しておくDBを作ります。

```
$ brew install imagemagick
  ①
```
①「画像をアップするぞ　（その１）」ライブラリをインストール。
（※無料です。今の所PCの挙動がおかしくなったりはしてません。）

```ruby:Gemfile
source 'https://rubygems.org'
（↑のすぐ下に↓を書いとけばOK！！）
gem 'carrierwave'
    ①
gem 'mini_magick'
　　　　　　　　②
```
①「画像をアップするぞ　（その２）」アップロード用gem
②「画像をアップするぞ　（その３）」画像サイズに関するgem

```
$ bundle install
```
つづく
【skyway】遠隔操作リモコンに遠隔カメラを埋め込みたい！

# はじめに
dotstudioに潜んでいるたくろーどんです．
話題のskywayを試してみたいと思います．
あんまり知識がないので，とても難しそうです．


# 遠隔家電操作リモコン
去年，JavaScript祭に向けて[複数の家電をスマートフォンから遠隔で操作できるリモコン](https://qiita.com/minwinmin/items/47518c53ebe62d185e54)をつくりました．
しかし，問題点があります．
よく外出していると，「本当に家電を消したのか？」「もしかして誤操作で勝手についたりしてない？」といった余計な不安を感じます．
なので，「そのスマホリモコンから映像みえるようにしたら良さそう！」です．

# どんな感じにするか
遠隔家電操作リモコンは，obnizというマイコンを使っており，JavaScriptでプログラミングできます．なので，webと相性が良いというイメージです．
なので，skywayのwebRTCをJavascriptで動かして，遠隔家電操作リモコンと組み合わせたら良さそうです．

# こんな感じ？
[全体的なコード](https://github.com/minwinmin/Smart-Remote-Controller)はこちらです．
前回作ったコードに，[skywayのsampleプログラム](https://webrtc.ecl.ntt.com/js-tutorial.html)を必要な部分だけ組み合わせました．
![smart_rimokon.png](https://qiita-image-store.s3.amazonaws.com/0/212276/35389f73-389d-96fa-8a64-9f05d9b057c1.png)
このリモコンはジェスチャー操作（スワイプやタッチ）で証明のON/OFFや明るさの切り替えができるようになっています．その操作画面の一角に映像が見えるようにしています．
今回は，PCのwebカメラを利用したのですが，実際はobnizにカメラをつけて配信できるようにする必要がありそうです．
それには，こちらの記事が参考になりそうなので試してみたいと思います．
[スマホを最高級電子部品として電子工作に組み込む（カメラ編）](https://qiita.com/wicket/items/a45cf72e64fc346f4fe2)


# 終わりに
skypeのように映像や音声のやり取りするようなチャットよりも，何かを映像で監視するという用途なら簡単に実装できそうです．
遠隔で何かを監視する，という用途でこれからも何かつくれたらな，と思います．
[研究室用途](http://www.ea.u-tokai.ac.jp/horisawa/main.html)だと，真空チャンバーの中にカメラを入れて実験風景を配信できたらいいなぁ，とかワクワクが広がります．
Associated Valueを含むenum型をCodableに準拠する

Raw Valueを `Int` や `String` にしたenum型は、比較的簡単に `Codable` に準拠できます。しかし以下のようなAssociated Valueを持たせたcaseを含むenum型は、デコード・エンコード処理を独自に実装する必要があります。

```Variant.swift
enum Variant: Codable {
    case bool(Bool)
    case int(Int)
    case string(String)
    case point(CGPoint)
    case rect(CGRect)
}
```

まず各case名と同じ `Codingkeys` を定義し、`encode()` を実装します。

```Variant.swift
extension Variant: Codable {
    enum CodingKeys: String, CodingKey {
        case bool
        case int
        case string
        case point
        case rect
    }

    // ...デコードの方法は後述...
   
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        switch self {
        case .bool(let value):
            try container.encode(value, forKey: .bool)
        case .int(let value):
            try container.encode(value, forKey: .int)
        case .string(let value):
            try container.encode(value, forKey: .string)
        case .point(let point):
            try container.encode(point, forKey: .point)
        case .rect(let rect):
            try container.encode(rect, forKey: .rect)
        }
    }
}
```

この実装でJSONエンコードを行うと、次のような結果になります。

```swift
let variants: [Variant] = [
    .bool(true),
    .int(123),
    .string("hoge"),
    .point(CGPoint(x: 100, y: 200)),
    .rect(CGRect(x: 10, y: 20, width: 30, height: 40))
]
let json = try! JSONEncoder().encode(variants)
print(String(data: json, encoding: .utf8)!)
```

```json
[
  {"bool" : true},
  {"int" : 123},
  {"string" : "hoge"},
  {"point" : [100, 200]}
  {"rect" : [[10, 20], [30, 40]]}
]
```

> オブジェクトの中身を見て型推定することになるため、REST APIのレスポンス型としては妥当ではないかもしれません。
> `UserDefaults` やローカルストレージへ保存する目的では問題ないでしょう。

このJSONをデコードする実装は次のようになります。

```Variant.swift
extension Variant: Codable {
    enum CodingKeys: String, CodingKey { ... }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if let value = try container.decodeIfPresent(Bool.self, forKey: .bool) {
            self = .bool(value)
        } else if let value = try container.decodeIfPresent(Int.self, forKey: .int) {
            self = .int(value)
        } else if let value = try container.decodeIfPresent(String.self, forKey: .string) {
            self = .string(value)
        } else if let point = try container.decodeIfPresent(CGPoint.self, forKey: .point) {
            self = .point(point)
        } else if let rect = try container.decodeIfPresent(CGRect.self, forKey: .rect) {
            self = .rect(rect)
        } else {
            throw DecodingError.dataCorrupted(DecodingError.Context(
                codingPath: container.codingPath,
                debugDescription: "Unknown case"
            ))
        }
    }
    
    func encode(to encoder: Encoder) throws { ... }
}
```

構造が一致しない場合は自分でハンドリングが必要です。
上記の例では `DecodingError.dataCorrupted` を投げるようにしています。

> 1つのcaseにAssociated Valueが複数ある場合は実装が難しくなります。
> 複数のAssociated Valueは1つの構造体(struct)にまとめ、これを `Codable` に準拠させるほうが簡単でしょう。

参考: https://medium.com/@hllmandel/codable-enum-with-associated-values-swift-4-e7d75d6f4370
PHPUnitのバージョンアップで起きた悲しい出来事

# PHPUnitのバージョンアップで起きた悲しい出来事

## 悲しい出来事

プラグインをふんふんふーんって更新してると、、、

![2019-02-22_10h23_06.png](https://qiita-image-store.s3.amazonaws.com/0/54588/f7d58ad2-824b-d012-f84f-8ea502e4b005.png)


テストがこけた！

何でこけたし

![2019-02-22_10h23_53.png](https://qiita-image-store.s3.amazonaws.com/0/54588/b57101fa-a1f1-2aa4-09da-8d68e273ebf3.png)

・・・え？  
テストケース内の関数の型指定？なんで？

## PHPUnitの更新

![2019-02-22_10h24_34.png](https://qiita-image-store.s3.amazonaws.com/0/54588/be017ea3-3094-b440-d0a7-853b30d28b96.png)


https://github.com/sebastianbergmann/phpunit/issues/3288

・・・は？なんで？  
そんな更新したら複数バージョンについて一つのテストで書けないじゃん。。。

(もちろん型指定とか書いたらPHPの古いバージョンのテスト通りません。。。)

テスト書けなくなったんで、バージョン切りますねーとか意味わからんし。。。

## とりあえずやったこと
PHPUnitのバージョン以下で固定化したよ！  
どこまで動いてるか調べるのめんどくさかったんで、元々動いてたバージョンで。。。

もうちょいなんとかならんすかね。。。
Firebase RealtimeDatabaseのTypeError: _app2.default.database is not a function firebase解消法

## 発生したエラー
`npm`と`Firebase RealtimeDatabase`を使用した個人開発をしていた時のこと。
`$ firebase serve`を行い、ローカルサーバにhostingしたURLに接続したら、何も表示されていなかった。
consoleを確認した所、次のエラーが発生していた。

```
TypeError: _app2.default.database is not a function firebase
```

## やったこと
npmの`firebase`モジュールから`firebase/database`をimportする

## 解決法
`firebase.database()`のコードがあるファイルに`import'firebase/database'`を記入する。

```firebase.js
import firebase from 'firebase/app'
import 'firebase/auth'
import'firebase/database'


const config = {
  apiKey: "***",
  authDomain: "***",
  databaseURL: "***",
  projectId: "***",
  storageBucket: "***",
  messagingSenderId: "***"
}

export const firebaseApp = firebase.initializeApp(config)
export const firebaseDB = firebase.database()
```

## エラーの原因
コンソールに吐き出されたエラーを直訳すると、firebase関数に`_app2.default.database`はないとのこと。
しかし、そんな関数自分自身使用していない。
Googleで`TypeError: _app2.default.database is not a function firebase`と検索してみた所、次の記事を見つけた。

[firebase.database is not a function](https://stackoverflow.com/questions/38248723/firebase-database-is-not-a-function)

この質問者と発生していたエラーは異なるが、同じ解決法で解消できた。

`firebaseRealtimeDatabae`を使用する上で必要なmoduleがそのファイル内になかったことで、`Firebase cosole`のDatabaseと接続できずエラーが発生したのだと考える。
Storyboardで親の親Viewに対してSpacing制約をかける

次の画像のようにSuperviewに対しては距離の制約をかけることが簡単にできます。SuperviewのさらにSuperviewに対して制約をかけたいときに躓いたので書いておきます。
<img width="376" alt="スクリーンショット 2019-02-22 10.14.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/327967/9483ced9-fcaa-8032-4310-22e6a51a2179.png">

#やりたいこと
RedViewとTopAnchorとViewのTopAnchorを0にしたい。
<img width="743" alt="スクリーンショット 2019-02-22 10.16.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/327967/5d2315d4-46b9-8d30-29f7-9fcacc87d3b5.png">

#解決方法

- コードで書く
    - これは当然可能ですが、できるだけStoryboardでやってしまいたい...
- Storyboard上でつなげる
    - この記事で紹介する方法です

###手順
Interface HierarchyでViewからViewを右drag&dropで線を引っ張ります。
<img width="401" alt="スクリーンショット 2019-02-22 10.18.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/327967/569393e8-a395-5684-35a7-37290a530b8d.png">

マウスをリリースするとどの制約を追加するか訊かれるので、今回はTopSpace to SafeAreaを選択します。このViewにはSafeAreaがあるのでSafeAreaにつながってしまいましたが、消しておけばViewに直接つながります。

<img width="409" alt="スクリーンショット 2019-02-22 10.19.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/327967/bcf19fba-6bd2-6aef-04ad-3f73b52efbb1.png">

EqualWidthやHeightなどの制約を追加するときにも一手間減って楽かも知れません。

#この方法はどうしても必要なときだけにしましょう
Spacing制約は基本的にSuperviewに対してか同じ階層のViewに対してかけるようにと公式ドキュメントでも薦められています。先祖に対して制約をかけるとConstraintsがややこしくなるのであまりよくありません。

では、どういうときに使うかというと、ScrollView上のViewが画面の外にはみ出ないように制約をつけるときなどです。このようなどうしても必要な場合以外はSuperviewへの制約で対応するようにしたほうが良いかと思います。
IoTセンサーとダイソーの電池式モバイルバッテリーは相性がいいかもしれない

# はじめに

貧乏IoTには100均が欠かせませんよね。

さて、以前から「もしかしたらな〜」と思っていて試していなかったこと。

*USBで電源供給できるIoTセンサー類のバッテリーに100均のやつが使えないか？*

まあいつか試そうと思っていて機会がなかったが、昨日ダイソーに行ったときに思い出したので108円(税込）の電池式モバイルバッテリーを買ってやってみました。

# やってみた

結論から言うと、うまくいきました。

![スクリーンショット 2019-02-22 9.47.47.png](https://qiita-image-store.s3.amazonaws.com/0/61995/7fe1e9a0-efe3-4d21-8d7c-b685c2d4422a.png)

オムロン環境センサ USB型（[2JCIE-BU](https://www.fa.omron.co.jp/products/family/3724/))をダイソーの電池式モバイルバッテリーにつけてみた。電源が入ってデータが送信され、途中で切れることがなかった。

1時間ほど環境センサのデータを[Ambient](https://ambidata.io/)に送ってみたらちゃんと送信されつづけていました。うむ、これはコスパがいい！

![スクリーンショット 2019-02-22 9.51.47.png](https://qiita-image-store.s3.amazonaws.com/0/61995/1eda1352-1349-7b37-6f50-8150b1009b86.png)

# なにがうれしいのか？

それ、なにがうれしいの？という方もおられると思うので、うれしいことを説明しておきます。要点は3つ

1. IoTセンサーにモバイルバッテリーが使える
2. 電池式モバイルバッテリーである
3. 超安い

です。

## IoTセンサーにモバイルバッテリーが使える

実のところ、多くのモバイルバッテリーはこういったセンサーやArduinoなどのマイコンで使えないもののほうが多く、[IoT対応モバイルバッテリー](https://www.amazon.co.jp/cheero-3200mAh-IoT%E6%A9%9F%E5%99%A8%E5%AF%BE%E5%BF%9C-%E3%83%A2%E3%83%90%E3%82%A4%E3%83%AB%E3%83%90%E3%83%83%E3%83%86%E3%83%AA%E3%83%BC-CHE-061/dp/B018KD0D82)という専用の製品が発売されているくらいです。

なぜそのへんに売ってあるスマホ等を充電する向けのモバイルバッテリーが使えないかというと、多くのモバイルバッテリーには一定量以下の電流を供給しない保護機能がついていて、センサーのような微弱な電流しか必要としない機器を接続すると、自動的に電力供給を停止してしまうからです。

なので、上記で試験しているオムロン環境センサUSB型を普通のモバイルバッテリーにつけると、最初電源は入るけど、しばらくすると電力供給が停止してセンシングできなくなる。といった状態になります。

一方でダイソーの電池式モバイルバッテリーはそういった保護機能がついてないらしく、電力供給が止まらないのでセンサーが使えるみたいです。

## 電池式がいいこともある

IoTでセンサーを運用する場合、最も検討が難しいのが電源です。電波の疎通もそうなんですが、安定して連続的に電力を供給することのほうが難しい場合も多いです。

センシングする拠点の近くに電源がない場合はモバイルバッテリーを採用するケースが多いですが、リチウムイオンバッテリーなどの充電式よりも電池式でやるほうが運用が安定するケースもあります。例えば、

*清掃などで人が定期的に往来する拠点でセンシングをする*

*定期的に機器をチェックする業務のついでにセンサーの状態も確認できる*

場合など。こういった場合には、モバイルバッテリーを交換するよりも電池を交換するほうが運用が楽な場合があります。充電式バッテリーの場合は、消費されたバッテリーを繰り返し充電するオペレーションが発生しますが、電池だとそれが発生しない。

普段は充電式乾電池を交換するオペレーションを行い、万一充電されている乾電池がなくなった場合は、通常の乾電池で非常対応できる。

といったように運用の選択肢が広がる場合があります。

## 超安い

言うまでもありません。100円です。

# まとめ

ネタ記事にみえて実は割とマトモなことを考えて書いています。IoT運用においてはエッジでの電源供給について多様な選択肢を持っておいたほうが実装で有利になります。その観点でダイソーの電池式モバイルバッテリーは特定のケースにおいてかなり実用的かもしれない思いました。

単三電池2本分の電力なので、消費電力の大きいセンサーだときついかも。電池交換するときにケース奥側の電池が取りにくいので交換作業がちょっとやりにくいかな。とか思うところがありますが、多くの小さなセンサーを配置する場合にはコスパ最強です。

個人的にはアリです。