OmniAICreator/Qiita-1.07M huggingface dataset:
tf.get_collectionの引数scopeで特定スコープのOperationだけを抽出

# 概要
GANとかだと、複数のネットワークがあって、それぞれにBatchNormalizationがある状況に遭遇する。このとき、一部のBatchNormalizationだけ更新したい。それには、tf.get_collectionをscopeを指定して用いれば良い。

# 詳細
## 前提知識
tf.layers.batch_normalizationを使う場合の訓練は、

```python
x_norm = tf.layers.batch_normalization(x, training=training)
                                                             
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
  train_op = optimizer.minimize(loss)
```
のようにして訓練時にtf.get_collectionでupdate_opsを取得します。

## 例
tf.get_collectionの第2引数にスコープを指定すると特定のスコープのものだけ取得できます。

``` python
import tensorflow as tf

with tf.variable_scope("Foo"):
    x = tf.zeros([5, 10])
    tf.layers.batch_normalization(x, training=True)

with tf.variable_scope("Bar"):
    x = tf.zeros([5, 10])
    tf.layers.batch_normalization(x, training=True)

print(tf.get_collection(tf.GraphKeys.UPDATE_OPS, "Foo"))
# [<tf.Operation 'Foo/batch_normalization/AssignMovingAvg' type=AssignSub>, <tf.Operation 'Foo/batch_normalization/AssignMovingAvg_1' type=AssignSub>]


print(tf.get_collection(tf.GraphKeys.UPDATE_OPS, "Bar"))
# [<tf.Operation 'Bar/batch_normalization/AssignMovingAvg' type=AssignSub>, <tf.Operation 'Bar/batch_normalization/AssignMovingAvg_1' type=AssignSub>]

```

# 確認環境
python3.6.6
tensorflow1.9.0
機械学習で似た顔を見つける（顔識別したい）試行錯誤

#顔識別したい
特定のモデルが学習していない顔写真を入れて、大量の画像からその人をみつけたい。
基本的にやることは同じで、画像を読ませてベクトルをだして類似性を計算するだけ。
で・・・ベクトル抽出が一番大事なんです。

結果的に普通に学習しても失敗します。
https://qiita.com/mokoenator/items/6807132ce59913186a9b#%E7%89%B9%E5%BE%B4%E9%87%8F%E3%81%AE%E7%AE%97%E5%87%BA
に書いたtriplet lossを使ってmarginをとるようにします。

##vgg16
なにもしらべないでVGG16をファインチューンしてみる。
俳優の動画を学習させるがいい結果がでない。
全結合層の値で類似性をみてもいまいち。
男女の区別もあやしい。（男女は人間が重要としているだけで機械的には関係ないのかも）
男性顔に対して男性よりも女性のほうが高類似とでてくる

いろんな画像をいれて類似度を計算するが、本人画像より他人のほうが似ている数値になる。

学習済みの俳優判定はすごいんだけど、特徴量で計算させるとダメ。
顔を認識してるように見えない。

学習に４時間～８時間かかる。暇すぎる

ちなみにファインチューンしないVGG16も同じくらいの精度。

###やったことは
・俳優さん数人の画像を集める
・opencvで顔認識＋切り出し（ゴミあり）
・ゴミ除去
・学習する＞このモデルをモデルAとする

・動画＞１フレーム切り出し＞opencvで顔だけ切り出し（ゴミあり）
・モデルAで俳優に該当すれば画像を該当俳優フォルダに保存
・モデルAで俳優に該当しない場合はかおじゃないフォルダに保存

・60％くらい振り分けに成功しているので手動で検査（ゴミ除去）
・顔かどうかあいまいなものは削除する
・本学習を行う

画像をフォルダに分ける作業がすごく大変。
服＋顔で判断してたのが、顔だけだと誰これ？？て状態になる。
確実に動画内の人間が一人なら楽なんですけど女優が数人移った動画だと振り分け作業に吐き気がしてくる
同じ女優でも表情が変わってると人間は認識できないみたい。
洋服や髪型の雰囲気＋変化する表情だからXXXさんって認識できてるんだなぁと思った。


動画の場合は同じような画像がおおくなるのでそれはだめじゃないか？と思う。
VGG16のモデルで同一と判断できる画像は消してもいいかなと思った。



##open face
https://cmusatyalab.github.io/openface/
CNNなの？コレでやってみる。
環境構築にやたら時間がかかる。

ベクトルがでるので、これを使って類似性を出す。
結果としてはNG。VGG16を自分でファインチューンしたほうがいいくらいかも。
判定してほしい画像が正面を向いてないとだめなのかな？
使い方がまちがってる？？
時間がかかったわりに成果なし

##vggface2
vggface2というのを発見！
学習済みデータを発見できないのでじぶんでやる。
https://www.robots.ox.ac.uk/~vgg/data/vgg_face2/
登録して8631人のデータを取得する。全部で40GByteくらいある。
（データ量との戦いになるのと思ってなかったのでSSDの空き容量がない。新しく購入）
さぁ！学習だ！！！
GTX1060で1epoch二日かかる計算。100epochで200日も。。。
ほかのGPUは実験中なのであきらめる。
（SSDのお金が無駄になった）

学習済みモデルがほしぃい


##keras-vggface
vgg faceを学習したモデルがあったのでそれを使う。
（vgg face2とは違う）
https://github.com/rcmalli/keras-vggface
この通りにインストールすればいい。
2622人を学習しているので期待できそうだ。
全結合層のfc8 (Dense)、fc7 (Dense)、fc6 (Dense)で類似度をとるが・・・
やっぱりだめだ。どの層で計算しても似てねぇ。

OUTPUTであるfc8/softmax (Activation)の値をみてみると、なんかイケてる数字だなぁ～～とおもったので
ここで類似度をだしてみる。
そこそこの感じがある。
男女もそこそこ分かれる。
2622人もあるとある程度バラケテくれるので、計算に使えるみたい。
なんか洋服とか髪型を見ている気がしてならない。


##keras-vggfaceをGrad Camでどこを見てるか？
ぱくたそを使わせてもらいます。
結果
![結果１](https://qiita-image-store.s3.amazonaws.com/0/185049/0283fb31-aad7-0147-4110-b7dfe615467a.jpeg)
ヒートマップの赤いところがどこを見ているか示している。
アスペクト比がおかしいのでわかりにくいかと思いますが、あんまり顔みてないよ。
なんで手をみてるんだ。。。

顔をアップに切り取ってみる
![結果２元](https://qiita-image-store.s3.amazonaws.com/0/185049/2f728580-a797-602b-b37a-2b8a427164d1.jpeg)
![結果２マップ](https://qiita-image-store.s3.amazonaws.com/0/185049/9675af3b-5940-2924-3c70-878a22f70333.jpeg)
あんまり顔みてないよ。

もしかしたら・・赤い部分を白トビさせて、青い～黄色くらいをのこして学習させればいいのかなぁ・・・

↓追記を参照


###Grad Camの注意？
Grad Camは判定したclassを逆に計算してるような感じなので
一度モデルに判定させて、classを特定する
特定したclassを逆に流し込んでヒートマップを作ってるようです。
なので
犬猫判定モデルに犬猫が混ざった写真で犬classを逆流させると犬が赤くなり、猫classを逆流させると猫が赤くなるみたい。

なんにしても、vggfaceは顔が赤くならないとだめだとおもう。



もしかして、スナップ写真じゃなくて
顔に髪かからなようにしていろんな表情を集めればOK？
坊主の人？？？
モジモジ君？


vgg face2に期待。



#感想
人間クラスから、さらに分かれた個人の類似性を判断するのはかなり難しい。
猫の個体識別が人間にとって難しいのと一緒なんだと思う。


今後は、坊主、モジモジ君の画像をあつめるか、Grad Camの情報を使って白トビさせてみようかな。

# 追記
いろいろ試してみたらkeras-vggfaceがすごくよいことが分かった。
単純に顔を切り取って試せばよい！！
GNU 系の date コマンドで１年前の次の日曜日の日時を取得する

GNU 系の `date` コマンドでは `-d` オプションにより、ある時刻からの相対的な日時を取得できる。

例１：今日 (`2018/07/16(月)`) から３日後

```bash
$ date -d '3 days' +%Y/%m/%d\(%a\)
2018/07/19(木)
```

例２：今日 (`2018/07/16(月)`) の次の日曜日

```bash
$ date -d 'next sunday' +%Y/%m/%d\(%a\)
2018/07/22(日)
```

例３：`2018/07/07(土)` の１年前

```bash
$ date -d '20180707 1 year ago' +%Y/%m/%d\(%a\)
2017/07/07(金)
```

例４：今日 (`2018/07/16(月)`) から来週の日曜日

```bash
$ date -d "next week sunday" +%Y/%m/%d\(%a\)
2018/07/29(日)
```

# 本題
１年前の次の日曜日の日時を取得することを考える。
直感的には `$ date -d 'last year next sunday'` で取得できそうであるが、実行結果は以下の通り。

```bash
$ date -d 'last year next sunday' +%Y/%m/%d\(%a\)
2017/07/22(土)
```

日曜日を取得したいにも関わらず土曜日を取得してしまう。
これは `date` コマンドが曜日の計算を優先して計算してから、去年の日時を計算しているため。

# 解決策
以下のように求めることができる。

```bash
$ date -d "1 year ago `expr 7 - \`date -d '1 year ago' +%w\`` day" +%Y/%m/%d\(%a\)
2017/07/23(日)
```

`+%w` を用いると日曜日を `0` として `0` 〜 `6` までの数値で曜日を算出できる。
これにより去年の日時の曜日を計算し、去年のに日時に一週間分の日数である `7` からその曜日分を引いた日数だけ、去年の日時に加算する。

下記のように `n` 年前、`n` 年後の日時の次の日曜日の取得にも一応適応できる。

```bash
$ date -d "2 year ago `expr 7 - \`date -d '2 year ago' +%w\`` day" +%Y/%m/%d\(%a\)
2016/07/17(日)
```

```bash
$ date -d "1 year `expr 7 - \`date -d '1 year' +%w\`` day" +%Y/%m/%d\(%a\)
2019/07/21(日)
```
[Angular] よく使われるモジュール達 - @NgModuleとは何か (4)

`@NgModule`とは何かを知るシリーズ4回目です。
Angular付属のよく使うモジュールの紹介です。

今までの記事です。

- [JavaScriptのモジュール - @NgModuleとは何か (1)](https://qiita.com/sengoku/items/a62cb8d75733b0321706)
- [JavaScriptモジュール vs. NgModule - @NgModuleとは何か (2)](https://qiita.com/sengoku/items/52085ad12d85193d65d6)
- [ブートストラッピング - @NgModuleとは何か (3)](https://qiita.com/sengoku/items/4416ecafddac7ddeac53)

# `BrowserModule`

アプリケーションをブラウザ内で実行するのに必要です。
ほぼほぼ必須ですかね。


```ts:使い方
import { BrowserModule } from "@angular/platform-browser";
```

# `CommonModule`

`NgIf`とか`NgFor`とかを使うのに必要です。
`BrowserModule`読み込めば入ってます。

```ts:使い方
import { CommonModule } from "@angular/common";
```


# FormsModule

`input`系のタグで`NgModel`を使うのに必要です。

```ts:使い方
import { FormsModule } from "@angular/forms";
```

# `ReactiveFormsModiule`

`NgModel`ではなく、新しい`FormGroup`と`FormControl`を使うのに必要です。

```ts:使い方
import { ReactiveFormsModule } from "@angular/forms";
```

# `RouterModule`

SPA(Single Page Application)を作る際に使います。

```ts:使い方
import { RouterModule } from "@angular/router";
```

# `HttpClientModule`

サーバとHTTPでやり取りするの使います。

```ts:使い方
import { HttpClientModule } from "@angular/common/http";
```
Android Spannableを使った文字装飾のオプション

【移行のお知らせ】[プライバシー上の懸念](https://blog.qiita.com/about-user-page-renewal-20200326/)により、Qiitaアカウントの削除を検討しています。
各投稿は個人blog( https://gateau.hatenablog.com/archive/category/Qiita )に移行しました。
今後も参照される方は、ブックマークなど移行をお願い致します。

---

[SpannableStringBuilder](https://developer.android.com/reference/android/text/SpannableStringBuilder) を使って文字を装飾する際に、setSpanで与えるflagsのそれぞれの挙動をまとめます。

[setSpan](https://developer.android.com/reference/android/text/SpannableStringBuilder.html#setSpan(java.lang.Object,%20int,%20int,%20int)) の定義
> public void setSpan (Object what, int start, int end, int flags)

> Mark the specified range of text with the specified object. The flags determine how the span will behave when text is inserted at the start or end of the span's range.

flagsはテキストを挿入するときにしか意味をなさないようです。
色をつけただけの例と、前後に"*"を挿入した例を貼ります。

![Screenshot_1531734616.png](https://qiita-image-store.s3.amazonaws.com/0/36199/c43dae2f-b7f7-ef0f-6164-af5b3f3d11d4.png)

```Kotlin:SetSpanActivity.kt
class SetSpanActivity : AppCompatActivity() {

    companion object {
        fun createIntent(context: Context): Intent = Intent(context, SetSpanActivity::class.java)
    }

    private val binding: ActivitySetSpanBinding by lazy {
        DataBindingUtil.setContentView<ActivitySetSpanBinding>(this, R.layout.activity_set_span)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        var decorateText = "SPAN"

        binding.textViewDecorateEE.highlight(Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, decorateText)
        binding.textViewDecorateEI.highlight(Spannable.SPAN_EXCLUSIVE_INCLUSIVE, decorateText)
        binding.textViewDecorateIE.highlight(Spannable.SPAN_INCLUSIVE_EXCLUSIVE, decorateText)
        binding.textViewDecorateII.highlight(Spannable.SPAN_INCLUSIVE_INCLUSIVE, decorateText)

        binding.textViewInsertEE.highlight(Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, decorateText, "*")
        binding.textViewInsertEI.highlight(Spannable.SPAN_EXCLUSIVE_INCLUSIVE, decorateText, "*")
        binding.textViewInsertIE.highlight(Spannable.SPAN_INCLUSIVE_EXCLUSIVE, decorateText, "*")
        binding.textViewInsertII.highlight(Spannable.SPAN_INCLUSIVE_INCLUSIVE, decorateText, "*")
    }

    private fun TextView.highlight(range: Int, decorateText: String, mark: String = "") {
        val originalText = text.toString()
        val start = originalText.indexOf(decorateText)
        val end = start + decorateText.length

        val colorSpan = ForegroundColorSpan(ContextCompat.getColor(context, android.R.color.holo_red_light))
        val builder = SpannableStringBuilder(originalText).apply {
            setSpan(colorSpan, start, end, range)
        }

        text = if (mark.isBlank()) {
            builder
        } else {
            builder.apply {
                insert(end, mark) // 文字位置がずれるので後ろから設定
                insert(start, mark)
            }
        }
    }
}

```
flexboxで段組をするときは、大量のテキストが入った場合を想定しよう

気付いている方は、けっこういるかも知れませんが…
Bootstrap4の可変グリッド（col-{breakpoint}-auto）には、本来の幅を超える改行が含まれないテキストが入ったときに崩れる不具合があります。
https://getbootstrap.com/docs/4.0/layout/grid/#variable-width-content

**本来想定されている見た目**

![Grid_system_·_Bootstrap 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/21117/ce0a84af-31fb-2c81-3fa2-881a29694d27.jpeg)

**開発者ツールで大量のテキストを流し込んだ状態**

![Grid_system_·_Bootstrap.jpg](https://qiita-image-store.s3.amazonaws.com/0/21117/b5528152-9ca3-2920-58e4-205fe7b348d1.jpeg)

これを修正しようとすると、ほぼすべてのグリッドに手を入れなければならないらしいので、ここではこの問題に関する解決策は割愛しますが、このような挙動が起こる原因について書いておきます。

## flex-shrinkの役割

結論から書くと、 flex-shrink:1 を指定していないためです。

こちらに、floatを使った場合と、Flexboxを使った場合のサンプルを作りました。
左に幅固定ボックス、右に幅可変ボックスとテキストがある、よくあるコンポーネントです。

https://codepen.io/webbingstudio/pen/jpWJLJ

３つめの「flexbox + flex-grow:1 &amp; flex-shrink:0」のパターンは、大量のテキストが入った場合に伸び切ってしまいます。
flex-growや、flex-basisを指定したときに、テキストが少ない場合のみで動作確認をしていると、この事故が起きやすくなります。

ウェブクリエイターボックスさんのチートシートでは、flex-shrinkの役割について、以下のように解説されています。

> flex-grow と逆で、親要素に余ったスペースがなくすべての子要素が入り切らない場合、指定のある子要素が他の子要素に対してどれくらい縮むかを指定します。
> https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet

つまりflex-shrinkは、flex-growではフォローできない、ボックスの幅が伸び切った際に適切な幅に制限する役割を持っているのです。
どのような要素が入るか予測できない可変ボックスでは、flex-growとflex-shrinkの両方を指定するのが良いと考えられます。

## 逃げるは恥だが役にt(ry

以上、flex-grow:1と一緒にflex-shrink:1も指定しようねという話でしたが、このような「何が入るのか、左側がどのような幅になるのかわからない」状況の場合、旧来の float + overflow:hidden とか、 display:table の方が無難なこともあります。

CSS Gridがもっと楽に使えるようになればそれに越したことはないでしょうし、理想ではあるのですが…
Leafletで地図を表示しようとしてなかなか表示されないと思ってたらブラウザーのサイズを小さくしたら表示された件


Leafletで地図を表示しようとして、全く地図が表示されず、試しにFirefoxを起動したら表示され、Chromeでは表示されないというなかなか奇妙な現象に半日を費やしてしまいました。

どうも地図の幅が800pxくらいを境に表示されなくなるようで、たまたまFirefoxのウインドウサイズが小さくて表示されてたようです。

関連する内容はここら辺と思われます。

https://github.com/Leaflet/Leaflet/issues/1266


## 環境

- Rails 5.2.0
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
- leaflet-rails (1.3.1)
- twitter-bootstrap-rails (4.0.0)



## 地図の表示

Railsプロジェクトの作成や、twitter-bootstrap-rails、leaflet-railsの実装は本題ではないので省略します。

github等を参照してください。

https://github.com/seyhunak/twitter-bootstrap-rails
https://github.com/axyjo/leaflet-rails

Homeコントローを作成しましたので、各種ファイルはhome.*になっています。


<a name="show_map_with_leaflet-rails"></a>

地図表示にleaflet-railsを使うと下の一行をviewに記述すると表示されるはずです。

```app/views/welcom.html.haml
#map
  = map center: {latlng: [51.52238797921441, -0.08366235665359283], zoom:18}
```

しかし、なぜか下のエラーが出たのでleaflet-railsの便利なヘルパーを使わずcoffeescriptで試すことにしました。

	Error: Map container is already initialized.
	
home.coffeeに[Leaflet](https://leafletjs.com)のサイトを参考に下のように記述しました。

```app/assets/javascripts/home.coffee
ready = ->
  map = L.map('map').setView([
    51.505
    -0.09
  ], 13)
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors').addTo map

$(document).ready(ready)
```

ここで、ブラウザーのウインドウサイズを小さくしないと表示されないことが発覚しました。

スタイルシートでmap要素のサイズが800pxより大きくならないように試してみたりしましたがうまくいかずしばらく対処方法が分かりませんでした。


## 原因

実はレイアウトでスマホのような画面サイズが小さいデバイスではbootstrapsの12カラムで表示するようにしていて、パソコンのような画面サイズが大きいデバイスでは前後に1カラム余白をとって10カラムで表示するようにしていました。

```layouts/application.html.haml
    .container
      .row
        .visible-xs.visible-sm
          .col-xs-12.col-sm-12
            = bootstrap_flash
            = yield
        .visible-md.visible-lg
          .col-md-1
          .col-md-10
            = bootstrap_flash
            = yield
          .col-md-1
```

どうも12カラム使用しないとうまく表示されないようで、800pxくらいを境に12カラム表示になったり10カラム表示なったりで、10カラムの時は表示されないという現象でした。

## 対処

12カラム表示だけで使用する用にレイアウトを変更しました。

```layouts/application.html.haml
	.container
	  .row
	    .col-xs-12.col-sm-12
	      = bootstrap_flash
	      = yield
```

これで地図がブラウザーのウインドウサイズに関わらず常に表示されるようになりました。

また、[leaflet-railsのヘルパーを使用した方法](show_map_with_leaflet-rails)でも問題なく表示されるようになりました。
エラーが出ていたのも12カラム表示することと関係したようです。
変数間の相関係数をリストとして大きい順に並べる

## やりたいこと
重回帰分析をするとき、多重共線性を避けるために相関が高い変数を見つける必要がある。
VIFを計算するライブラリもあるが、ここでは相関係数（の絶対値）を大きい順に並べたリストの作成方法を紹介する。

なお、このページはStack Overflowの以下記事を参考にしています。
[Show correlations as an ordered list, not as a large matrix | Stack Overflow](https://stackoverflow.com/questions/7074246/show-correlations-as-an-ordered-list-not-as-a-large-matrix)

## サンプル

### データの準備

```R
df = data.frame(a=1:10,b=20:11*20:11,c=runif(10),d=runif(10),e=runif(10)*1:10)
z = cor(df)
```

### 相関係数の計算
`cor()`関数を使うと下のようなマトリクスができる。
5×5のマトリクスぐらいなら人間の目で相関の高い変数を見つけることも可能だが、これより変数の数が増えると厳しい。

```R
           a          b           c           d          e
a  1.0000000 -0.9966867 -0.38925240 -0.35142452  0.2594220
b -0.9966867  1.0000000  0.40266637  0.35896626 -0.2859906
c -0.3892524  0.4026664  1.00000000  0.03958307  0.1781210
d -0.3514245  0.3589663  0.03958307  1.00000000 -0.3901608
e  0.2594220 -0.2859906  0.17812098 -0.39016080  1.0000000
```

### リストへの変換

```R
z[lower.tri(z,diag=TRUE)]=NA  #Prepare to drop duplicates and meaningless information
z=as.data.frame(as.table(z))  #Turn into a 3-column table
z=na.omit(z)  #Get rid of the junk we flagged above
z=z[order(-abs(z$Freq)),]    #Sort by highest correlation (whether +ve or -ve)
```
以下のような形で出力を得られる。便利。

```R
         Var1    Var2    Freq
6        a       b       -0.9966867
16       a       d       -0.7705183
17       b       d       0.7578559
11       a       c       0.5856587
12       b       c       -0.5721143
22       b       e       -0.4459712
18       c       d       -0.4237590
21       a       e       0.3861569
23       c       e       0.3011528
24       d       e       -0.2713602
```
kubernetesでprivate repositoryからimageをpullする

secretオブジェクトを作る

```
kubectl create secret docker-registry --dry-run=true $secret_name \
--docker-server=<DOCKER_REGISTRY_SERVER> \
--docker-username=<DOCKER_USER> \
--docker-password=<DOCKER_PASSWORD> \
--docker-email=<DOCKER_EMAIL> -o yaml > docker-secret.yaml
```

使うときは、imagePullSecretsで$secret_nameを指定

```
apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: <上で指定したsecret_name>
```

gcrを使う場合

json_keyを使って認証
https://cloud.google.com/container-registry/docs/advanced-authentication


```
kubectl create secret docker-registry $SECRETNAME \
  --docker-server=https://gcr.io \
  --docker-username=_json_key \
  --docker-email=user@example.com \
  --docker-password="$(cat k8s-gcr-auth-ro.json)"
```

namespaceを指定するのを忘れないように
新旧比較のミスディレクション

# 新旧比較のミスディレクション
## ミスディレクション

「観客の視線や思考を事実とは違った方向に向けさせる」手法。マジックやミステリー小説に使われる手法。漫画「黒子のバスケ」でおなじみの手法。ミステリー小説の場合は、「ミスリード」といった方が自然かも。


ミスディレクションは三つに分類されます。

①サイコロジカル(心理的)ミスディレクション
②フィジカル(身体的)ミスディレクション
③タイム(時間)ミスディレクション

・・・って、なんでこんな書き出しなのかというと、ミスディレクションと障害原因がつながった感じがして、特に、①と②のミスディレクションにハマったのだなぁと思うところがあり、ちょっと興味深かったのでご紹介。③タイムミスディレクションのネタがあると投稿ネタ的にはもっと良いんだけれど・・・。

## サイコロジカルミスディレクション
```
エンドユーザ：「この前のAシステムのコード追加修正で、
Aシステムに入力した「△△金額項目」がBシステムの「□□帳票」に印字される筈なんだけど、
印字されていない。なんで？」
```
```
私：「確認いたします。」
```
```
私：「確かに印字されていない。Aシステムを調べていくと・・・
あれ？この間●●さんのテスト結果レビューしたけれど、
そこで「■■項目」のコード追加してた。でも、このif文の条件分岐だと印字されないじゃん。」
```
```
●●さん：「ごめん、ごめん。この前の「■■項目」のコンボボックスコード追加で修正漏れ。」
```
```
私：「・・・」
```

遡ること数日前。
Aシステムのとある項目に新たに運用するコードを追加するというもの。Web画面の入力チェックを追加、変更して、コンボボックステーブルに新コードのレコードを追加して・・・後続のBシステム向けファイルIFもコード追加があるので、関係者にも連絡してと、修正箇所が多岐にわたる案件。

●●さんの他にレビューアが2名。レビューアの内の1名が自分。

```
●●さん：「・・・ということで単体テストの結果は以上です。」
```
```
私:かれこれ1時間。まだ続くのか？！・・・
```
```
●●さん：「現状保証は、後続Bシステム向けファイルの新旧比較で行いました。
**立ち上げ以降全トランザクションデータがありましたので、
それで新旧比較を行いました。**これがdiff結果です。
**今回のコード追加で影響を受けた箇所が差として出ています。
余計な影響は出ていません。**」
```
```
レビューア、私：「・・・差がｎ箇所と。問題なさそうですね。OKです。」
```

レビューイ、レビューア共に色々問題ありなのですが(**影響調査はどうだったのか？とか**)、ミスディレクションになっているところはと言うと・・・。

「**立ち上げ以降全トランザクションでテスト**」という言葉から、レビューイ、レビューアの皆の心理がどうなったか？「**過去データ全部使っているんだから、現状保証できている**」と安心してしまった。(本当は「■■項目」に新コードを追加した結果、別の項目との関連で修正漏れがあって「△△金額」が計算されないのに)。

「**余計な影響は出ていません。**」という言葉も、「**余計な差が出ていない＝余計な修正をしていない＝現状保証できている＝安心**」というサイコロジカルミスディレクション。

## フィジカルミスディレクション
さらに、フィジカルミスディレクション(視覚に作用)もありました。
それはdiff結果です。視覚的に差が見えるので、その差の部分に誘導されてしまいました。
本当は、差がでる項目があった筈なのに、**差が出たところだけ**を一つ一つ確認してOK,NGを判断してしまいました。

## ミスディレクション例
これらのミスディレクションは、形を変えていろんな所に潜んでいます。

例えば、テスト機から本番機に3件データ移行。データ移行後の新旧比較のdiffで3件のレコードが差として出て移行OKとしたが、その後、ユーザ指摘で障害。なぜか？そもそもテスト機から抽出したデータが間違ったレコードだったから。

例えば、10個のソースのうち5個を修正。本当はその要件を満たすには、6個目も修正が必要。
diffの結果、5個差が出る。レビューイは余計な修正して無いと言い、レビューアは5個の差が出ている結果を見せられて、それに引きずられてOKと言ってしまう。

## 振り返り
「**立ち上げ以降全トランザクションでテスト**」「**余計な影響は出ていません。**」という**言葉**から、皆が安心してしまいました。
「**差が出たところだけ**」を**見て**、皆が安心してしまいました。
どちらも、「**聞く**」や「**見る**」から「**始まっている**」ところに問題がありそうです。
「**無防備な状態**」で聞いたり、見たりしてしまうと、それにロックオンされてしまい、別のルートがあるのに気づかず、結果しくじっています。

## 教訓
では、どうするか？見落としとか完全に防げないので100点取れないですが。。。

### ①「**予め、期待値=合格条件を持つこと**」
です。当たり前すぎるけれど、これです。「**テストファースト**」といってもいいかも。

レビューアは、結果を聞いたり、見る前に、「**期待値=合格条件を持つ**」ことができれば気づくチャンスが生まれます。

レビューイも「**予め、期待値=合格条件を持つこと**」ってから、影響調査していれば、その後の実装漏れが防げたかもしれません。

### ②「**期待値=合格条件と結果で2回レビューする**」
何もかもが終わって最後に全部の結果をレビューすると、その結果がミスディレクションになることもあります。「**期待値=合格条件**」が正しく定義できているか1回目のレビューを行う。「**結果が期待値=合格条件通りか**」2回目のレビューを行う。

です。
crystalを少し触ったので、ここに書いとく

# crystalを少し触ったので、ここに書いとく

##環境
crystal 0.25.1
Zorin OS 12.3

##概要
rubyやってるからついでにcrystalもやってみようと思って触ってきました。
多分今後、crystalに触れる事は少なくなるので、ここに感じた事など書き留めておきます。

### crystalとは
ruby風の文法で記述できる静的型付け言語です。
LLVMを使用しており高速であり、ベンチマークテストでは、よくTOP１０に食い込んでます。
crystalの基本文法は[このサイト](https://crystal-lang.org/docs/)で、学習できます。
もっと詳しく知りたい人は[公式サイト](https://crystal-lang.org/)を見てください。

### 型の指定
静的型付けだけあって型はしっかりかけます。
下の例では、引数であるnumにInt32型を指定し、渡す値もInt32を使っています。

```ruby:型指定
def disp_num(num : Int32)
  puts num
end

disp_num(2_i32)
```

```terminal:結果
2
```

ただし強制ではないので、rubyのようにもかけます。
この場合、Int32で足りる数値範囲ならデフォルトでInt32になります。

```ruby:型未指定
def disp_num(num)
  puts num
end

disp_num(2)
```

```terminal:結果
2
```

### メタプログラミング
静的型付けの言語でもメタプログラミングができるのだと驚きました。
crystalはmacroを使用することでコンパイル中にastを返却しメタプログラミングを可能にします。
下に簡単な例を記載しました。

```ruby:メタプログラミング
macro meta_test(name, num)
    def {{name}}
        {{num}}
    end
end

meta_test output_num, 100
p output_num
```
```terminal:結果
100
```
Hook処理なども多数あるので、良し悪しは置いといてゴーストメソッドなどのテクニックも使えるでしょう。
下記の例では、macro method_missingがhoge, fugaなどの存在しないメソッドに対して動作します。

```ruby:メタプログラミング２
macro method_missing(call)
    print "存在しないメソッドが呼ばれました", '\n'
    print "名前:", {{call.name.id.stringify}}, "引数の数", {{call.args.size}}, '\n'
end

hoge 100, 200
fuga
```
```terminal:結果
存在しないメソッドが呼ばれました
名前:hoge引数の数2
存在しないメソッドが呼ばれました
名前:fuga引数の数0
```


### ポインタ
crystalでは、pointerofメソッドを使って参照渡しが可能です。
下記の例では、numに100を代入した後に参照渡しを使い200に上書きしています。

```ruby:参照渡し
def update_num(ptr, value)
    ptr.value = value
end

num = 100
update_num(pointerof(num), 200)
p num
```

```terminal:結果
200
```
### おまけ
他にも色々面白い事ができるので、ちょっとだけ紹介。

#### crystalとcは仲良し
記述量が多くなるので省略しますが、crystalはrubyにはないenumや構造体が使えます。
また、Cのlibrayをcrystal内から呼び出すことも可能です。
詳しくは、[C bindings](https://crystal-lang.org/docs/syntax_and_semantics/c_bindings/)を読んでください。

#### 数値の表記
crystalは数値を見やすいようにアンダースコアで区切ることができます。
下記のような感じで使えます。

```ruby:数値の表記
puts 1_0_0_0_0
```
```terminal:結果
10000
```

電話番号とか郵便番号とかに使うとコードの可読性があがるでしょう。

#### Go言語っぽいswitch文
_をつけて、値をなくすのはGoではよくある手法ですがcrystalのswitch文でも、それが可能です。

```ruby:switch
case {1, 3}
when {1, _} then puts "左が１です"
when {_, 2} then puts "右が２です"
when {1, 5} then puts "左１で右が５です"
end
```
```terminal:結果
左が１です
```
こんな感じでcrystal独自のものが結構あって面白いです。

### 感想
ruby3.0が静的型付けを方向性の１つとして指し示していますが、crystalみたいな
感じになるのかなと個人的に思いました。
rubyをやっている人は、文法が似ているのですぐにチュートリアルが終わるかと思います。
使える言語は増えれば増えるほど楽しいので、是非crystalに挑戦してみてください。
MSX JIFFY

[2章 割り込み - MSX Datapack wiki化計画](http://ngs.no.coocan.jp/doc/wiki.cgi/datapack?page=2%BE%CF+%B3%E4%A4%EA%B9%FE%A4%DF)

```jiffy.c
/*
z88dk / WebMSX
zcc +msx -lndos -create-app -bnjiffy jiffy.c

10 cls
20 print chr$(11);peek(&hfc9f);peek(&hfc9e);
30 goto 20
*/

#include <stdio.h>

void main()
{
	int *jiffy = (int *)0xfc9e;

	printf("\xc");
	for (;;) {
		printf("\xb %d", *jiffy);
	}
}
```
Deep Painterly Harmonization を試す(2018 年 7 月 16 日時点)

漢なら Deep Painterly Harmonization やりたいですね!

https://github.com/luanfujun/deep-painterly-harmonization

Last author が, Advanced Global Illumination https://www.amazon.com/Advanced-Global-Illumination-Second-Philip/dp/1568813074 の共著者で, 大域照明などの研究で有名な Kavita Bala 先生 http://www.cs.cornell.edu/~kb/ で強い.

これはもうやるしかありませんね, やりましょう!

できました.

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">ねんがんの Deep Painterly Harmonization の実行にせいこうしたぞ!!!!! ㊗️㊗️㊗️㊗️㊗️㊗️😆😆😆😆🎉🎉🎉🎉🎉✌️✌️✌️✌️😻😻😻😻😻🙏🙏🙏🙏🙏✨✨✨✨✨💪💪💪💪💪😤😤😤😤😤💮💮💮💮💮💮💮💮💯💯💯💯💯💯💯💯 <a href="https://t.co/x5a7T4qvWt">pic.twitter.com/x5a7T4qvWt</a></p>&mdash; Syoyo Fujita (@syoyo) <a href="https://twitter.com/syoyo/status/1018736223542628352?ref_src=twsrc%5Etfw">July 16, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 動かす.

上記の author の実装よりは, fast.ai で再実装しているこちらが動かすのに便利でした.

https://sgugger.github.io/deep-painterly-harmonization.html

適当に合成用に CG 画像を用意しましょう.
NanoRT で大域照明画像をレンダリングするのがおすすめ!

https://github.com/lighttransport/nanort

合成には, 1080 Ti で 5~10 分(first pass で 2~3 分, second pass で 5~7 分)かかりました.

やっていることは最適化なので, Fast Neural Style Transfer のように事前に特定のスタイルを学習させることで, 高速化させることができそうな雰囲気がありますね.

## TODO

* モバイルでうごかしたい
* 高速化したい
* **優秀な高速 Deep Painterly Harmonization 若人が人類史上最速で育成される**スキームを確立する旅に出たい.
AWS LambdaからFirestoreに書き込む

趣味開発でAWS LambdaからGoogle傘下サービスFirebaseのFirestoreへデータを書き込みをしたい需要が発生したため試した。

# 環境
- OSX HighSierra
- AWS CLI 導入・設定済
- Node v10.6

# firebase-adminインストール
```
yarn add firebase-admin
```

# ソース
https://firebase.google.com/docs/firestore/quickstart

公式のクイックスタートを参考に以下コードをざっと書く。

```javascript:index.js
const admin = require("firebase-admin");
  const serviceAccount = require("./serviceAccountKey.json"); // FirebaseのWebコンソールから落としてくる。
  const app = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "" // 略
  });

const db = admin.firestore();
const docRef = db.collection("users").doc("alovelace");

const setAda = docRef.set({
  first: "Ada",
  last: "Lovelace",
  born: 1815
});
```

nodeモジュールを含むためzipで固めてデプロイ。

# 実行時エラー発生
いざLambdaコンソールでテスト実行すると以下のエラーが発生してFirestoreのメソッドが機能しない。

```
Error: Failed to load gRPC binary module because it was not installed for the current system
```

# 原因と対処
https://medium.com/@samstern_58566/how-to-use-cloud-firestore-on-aws-lambda-4bf6d3a473d9

要するに、ローカル開発環境とデプロイ先Lambda環境間における、

- OSの差異 (ローカル=OSX, Lambda=たぶんAmazonLinux)
- Nodeバージョンの差異 (ローカル=v10.6, Lambda=v6.10)

が原因っぽい。

一旦node_modulesを削除。
lockファイルも削除。

```
rm -r node_modules
rm package-lock.json yarn.lock
```

Dockerのnode:6.10イメージを使ってnodeモジュールを落としてくる。

```
docker run --rm -it -v "$PWD":/worker -w /worker node:6.10.3 npm i --silent
```

再度zipで固めてアップロードしたらちゃんとFirestoreに書き込めた。
ちなみに、 LambdaはNode v8.10も対応しているのでv8.10に切り替えてのデプロイも試みたが、なぜか上手くいかなかったので深追いせずv6.10で妥協。

# 参考
[https://firebase.google.com/docs/firestore/quickstart](https://firebase.google.com/docs/firestore/quickstart)
https://stackoverflow.com/questions/39436072/cannot-destroy-firebase-connections-making-hot-lambda-fail-due-to-firebase-app
https://stackoverflow.com/questions/47979568/aws-lambda-error-failed-to-load-grpc-binary-module-because-it-was-not-installed
https://github.com/firebase/firebase-admin-node/issues/247
https://medium.com/@samstern_58566/how-to-use-cloud-firestore-on-aws-lambda-4bf6d3a473d9
https://www.npmjs.com/package/node-pre-gyp
Jettyを組み込んだjarファイルをEC2にデプロイする

# はじめに
前回、EC2にJettyをインストールしました。
[AmazonLinuxにJettyを導入してデモサイトを起動してみる](https://qiita.com/segur/items/e61f5198042b191f2aaa)

しかし、Jettyをjarファイルに組み込んでしまえば、そもそもJettyをEC2にインストールする必要がないことがわかりました。今回はそのデプロイ手順を紹介します。

Jettyをjarファイルに組み込む方法はこちらでは紹介しませんので、ご了承ください。


# jarファイルをデプロイする

カレントディレクトリに以下の２つがあるとします。

- Jettyが組み込み済みのjarファイル
    - 例. **SampleProject-0.0.1-SNAPSHOT.jar**
- sshアクセスのための秘密鍵
    - 例. **sample-project.pem**

デプロイ先のEC2のアドレスがxxx.yyy.zzz.wwwの場合、以下のコマンドでデプロイできます。

```bash
# jarファイルをアップロードする
scp -i ./sample-project.pem -r ./SampleProject-0.0.1-SNAPSHOT.jar ec2-user@xxx.yyy.zzz.www:~/

# sshでEC2にログインする
ssh ec2-user@xxx.yyy.zzz.www -i ./sample-project.pem

# サンプルプロジェクトをJettyで起動する
java -jar ~/SampleProject-0.0.1-SNAPSHOT.jar
```

これで、 http://xxx.yyy.zzz.www:8080 にアクセスしてみると、jarファイルの内容に応じたサイトが表示されるはずです。


# インスタンス起動時に自動起動するようにする。

まず、/etc/init.d/にシェルスクリプトを作成します。

```bash
sudo nano /etc/init.d/SampleProject.sh
```

シェルスクリプトの中身は以下のようにしてください。

```bash
#!/bin/sh
# chkconfig: 2345 99 10
# description: start jetty SampleProject
 
java -jar /home/ec2-user/SampleProject-0.0.1-SNAPSHOT.jar
```

上記の内容でスクリプトを保存したら、以下のコマンドを実行します。

```bash
# 管理者に実行権限を与える
sudo chmod u+x /etc/init.d/SampleProject.sh

# chkconfigにスクリプトを追加
sudo chkconfig --add SampleProject.sh

# マシン起動時にスクリプトを実行するように設定
sudo chkconfig SampleProject.sh on
```

これで自動起動するようになります。


# 最後に
これだけで、Webアプリのデプロイが完了しました。Jettyは便利ですね。
PHP Conference kansai 2018

割と適当なメモ書き。

## Project ICKX のあきらさんの話

普段はPHP5.3.3→PHP7.2.* へ上げる作業。ハードだった。

[FlyWheel2](https://wkbd.ickx.jp/fw/)の話

## Flywheel2: Rapid Application Development Framework.

2010年あたりに、使いやすいやつを作った。

## フローコントロール

コントローラはCakePHPみたいな感じになっている。ルータからはコントローラ名→アクション名で実装。

### コントローラ

値、状態を管理して、制御実行の流れを制御

1. Validation
2. Action
3. DisplayView, DisplayUserError, Forward, Redirect

Web,Cli問わずに、本来的に必要とされる機能を実装。（2010年当時のPHPにはなかったのよ、ホントに）

### アクション

例えばポイントシステムがあった時：アクションは大きいくくり。

ルールでアクションの流れを決める。

配列で記述した設定ベースで動く感じっぽい。

 source code 解説


# 普通のPHPがPixivになるまで

tadsanさん。

## Pixiv

作品7000万、画像は14,000万以上
apache httpd を 53台でさばいている

## pixiv.git

一つのリポジトリにそれぞれのサービスのサービス＋ライブラリが入っている

Realworld of Pixiv の補足

1. framework は使ってない: はじめから使っていないため。
2. フルスクラッチはしない。コード量が多すぎるため。

## 歴史図

- 2012年初め synfony
- 2013年 pixiv.git
	- submodule 大丈夫？
	- けどまぁ意外と。。。

## ふつうのPHP とは？

- apache + mod_php
	- 昔からの documentoRoot にあるphp
	- /member.php?id=10111... ←これ
	- seoの都合で残ってる
- LAMP
- テンプレートエンジンは smarty を使っている


### Apprunner

- 由来不明
	- try/cache や whoops など


### 2018年ごろ

URLとファイルは切り離されて、連想配列で挙動を切り替える形。

### クラス

- PSR0 で統一
- Classは static で使っている（去年のスライドで）
	- 昔に書かれたClassが良くなかったので、一度 static クラスにして、とりなおしをしている。

### PDO 問題

- 全てのクエリーは文字列に書いている…
- IN 句が素のPDOでは難しいので、PxvSqlを作っている。
- PDOラッパー
	- 読み込み、書き込みを切り分けて使うことが可能

## 新機能はどうする？

- 実装されたブランチをリリースする時マージ
	- 意図していない時にビッグバンマージが起きる
- 先にマージさせておいて、実行されないように
	- 理想としてはこっち。


有効無効：IPアドレスではなく、devtoggule を作っている。

管理画面から devtoggle クッキーを設定していれば、クッキーを見て挙動を切り替える。


# LT 

DBのFixture を作った話

- https://speakerdeck.com/tanakahisateru/shui-kahuikusutiyashu-itekurerunnaraan-motesutoshu-kuwa
- https://github.com/tanakahisateru/QuickBrownFox-demo
- https://packagist.org/packages/lapaz/quick-brown-fox
Salesforceの「商品」及び「価格表エントリ」を一括インポート・編集する方法

# これは何？
Saleforceに「商品」と「価格表エントリ」を一括インポートする方法です。
商品と価格表エントリにデータを入れることで、商談から商談商品を追加するときにインポートした商品が表示されます。
商品だけインポートしても、商談商品には追加できないので注意してくださいね。

# 必要なツール
## Google スプレッドシート
スプレッドシートを使います。

## G-Connector for Salesforce(Chromeアドオン)
一括インポートは、Chromeのアドオンを使います。
`G-Connector for Salesforce`というアドオンです。

2週間？までは無償で使えますが、それ以降は有償で、月３０$くらいかな？
有償ですが、十分に使う価値のあるツールです。
定期的にスプレッドシートの情報をSalesforceにアップロードしてレコード更新したりもできます。
https://chrome.google.com/webstore/detail/g-connector-for-salesforc/inpioilbljppoobbblcpbpjplkefmkep

なお、G-Coonector for Salesforceの使い方は、以下のサイトに分かりやすく書いてありました。
以下のサイトで十分分かりやすいので、本記事ではG-connectorの使い方は割愛しています。
２〜3回使えばもう慣れてくる、シンプルなツールです。

```
Salesforceを簡単更新！Googleスプレッドシート上でSalesforceデータの一括編集をやってみた！
http://www.sunbit.co.jp/blog/2018/02/702/
```

### 番外編（Excelを使う場合）

スプレッドシートではなくExcelでもできそうですが、僕は試していません。
（エクセルだとPCにそれなりにパワー無いと重いんだもん・・・）

sforce Excel Connector を使用して、商品および価格表情報をインポートする
https://help.salesforce.com/articleView?id=000007475&language=ja&type=1

# 手順
ざっくり手順は以下の通りです。

## 1. G-connectorで、Get Data Using SOQLを使って、「商品」のレコードを取得する。
G-connectorでデータを取得します。この際に表示カラムを選択できますが、全て選択します。
すでにデータがもしあれば、こんな感じで取得できるはず。
<img width="1167" alt="スクリーンショット_2018-07-16_17_13_29.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/30859/60a877f5-6f18-33d9-2166-b7baeeb7bead.jpeg">


## 2. 「商品」の必須カラムを埋めて、「商品」のインポートデータを作る
(1)のスプレッドシートに、インポートする商品を登録していきます。
登録するカラムはそれぞれ違うと思いますが、一般的はこんな項目でしょうかね。
あと、IsActiveは、 `TRUE` にします。

```
| Description | ProductCode | Family | Name | | IsActive | fixedPrice__c |
```

## 3. G-connectorで、Update/Insert/Upsert selected Row(s)を行って、Insertする。
(2)で追加した行（インポートした行）を選択して、G-connectorで、Update/Insert/Upsert selectedRow(s)を行って、Insertします。

インポートすると、スプレッドシートの右の方のカラムに、結果が表示されます。
<img width="513" alt="スクリーンショット 2018-07-16 17.20.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/30859/ba5a6aea-29cc-5fab-df45-c7d90ad1aad4.png">


## 4. G-connectorで、Get Data Using SOQLを使って、再度「商品」のレコードを取得する。
商品レコードを再度取得して、きちんと商品レコードが登録されているか確認します。
また、商品レコードの情報は価格表エントリを登録するときにも使うので、閉じずにそのままにしましょう。


## 5. G-connectorで、Get Data Using SOQLを使って、「価格表エントリ」のレコードを取得する。
次に価格表エントリを取得します。
別のシートが自動的に作られると思います。

## 6. (4)でレコード作成したデータを使って、価格表エントリの必須カラムを埋める
インポートするデータを作っていきます。
標準のカラム構成であれば、以下のカラムは入れることになるでしょう。

```
| *Pricebook2Id | UnitPrice | *Product2Id | ProductCode | Name | IsActive | 
```

で、「※」のカラムだけ補足します。
・PriceBook2ID
このカラムには、「価格表」のIdを入れます。
標準であれば、「Standard Price Book」のIdになると思います。
同じ価格表に登録する場合は、全て同じ値を入れます。

価格表のIdは、「価格表」のページにいって、URLみれば分かります。
たぶんこんなURLになっていて、01s7F...がIDですね。
```
https://salesforce/lightning/r/Pricebook2/01s7F000008hogehoge/view
```

・Product2Id
ここには、商品のIdを入れます。
(4)で取得したデータに、Idカラムがありますので、その値を入れます。
つまり、ここで、価格表エントリと商品の紐付けを行います。

・IsActive
こちらはTrueにします。

## 7. G-connectorで、Update/Insert/Upsert selected Row(s)を行って、Insertする。
インポートする価格表エントリの行を選択して、インポートします。


以上です。

かなり粗いので間違いがあったらご指摘お願いします！
デバッグ時にUIKitを読み込む

iOSアプリのデバッグ時に

```
po self.view.frame
```

としたときに表示できないことがある。これはUIKitが読み込まれていないからで、

```
expr @import UIKit
```

とすればよい。
これを自動的に行うには `~/.lldbinit` に書いておけばよいが、ただし、Xcodeが起動した時にはデバッグセッションが存在していない。
デバッグを開始するたびに新しいデバッグセッションが作成されるため、そのタイミングで読み込む必要がある。これを行うには、一度しか呼ばれない関数にブレークポイントを作成して、auto-continue属性をつけて、コマンドを設定すればよい。
Objective-Cだとこんな感じ。(didFinishLaunchingWithOptionsでもよい)

```
br set -F "-[CRAppDelegate application:willFinishLaunchingWithOptions:]" -G True -C "expr @import UIKit"
```

どうやらSwiftだと必要ないみたい。
kotlin でandroid入門　Preferences

アンドロイドでデータを保存する方法は
1. プリファレンス(Preferences)
2. 内部ストレージ
3. ユーザー設定
4. データベース
5. 外部ストレージ

## プリファレンス(Preferences)
アプリローカルなキーと値がペアになった端末のローカルなデータ
（自分の認識。基本どこにデータがあるか関与していないデータ)

### キー

キーと値のペアは、１つのプリファレンス(ファイルのイメージ)に保存され
1アプリに複数のプリファレンスを持つことが可能(なのか？)
プリファレンスもキーでアクセスする
val でも string.xml で string name で宣言しても使用可能でした

### プリファレンスの呼び出し

最初はプリファレンスそのものを

```kt
    val prefs = getSharedPreferences(PREFERENCES_KEY, AppCompatActivity.MODE_PRIVATE)
```

onCreate()外でも使いたいので遅延初期化を使って

```kt
    lateinit var prefs : SharedPreferences
    override fun onCreate(savedInstanceState: Bundle?) {
        // string nameの場合を例に
        prefs = getSharedPreferences(getString(R.string.preferences_key), AppCompatActivity.MODE_PRIVATE)
```

としておくと使いやすかったです

### 値の取り出し

値の型別に getString() / getInt() / getBoolean()
などがあり、型に合わせ使用する

```kt
    // getSharedPreferences()済のプリファレンスからDATA1_KEYの文字列値を取得
    //  getxxx()の第2引数は、値がなかった場合のデフォルト
    val memo : String = prefs.getString(DATA1_KEY, "memo")
```
memoに保存されている文字列が入ります
保存されていなかった場合は "memo" が

### 値の保存

取り出し時と同じ用に型に応じたメゾットがあるので
putString() / putInt() / putBoolean()

```kt
    val msgData : String = "値"
    val e : SharedPreferences.Editor = prefs.edit()
    e.putString(getString(R.string.preferences_key_data1) , msgData)
    e.apply()
```

で保存できます
JS基礎ーthisの指す先

# thisとは
this は function を呼んだ時の**呼び出し元**オブジェクトを指している

## 例(自分自身の性別取得したい)
```javascript

function getGender() {
    return this.gender;
}

var ma = {
    name: 'ma',
    gender: 'male',
    myGender: getGender
};

ma.myGender(); // 'male', 予想通り
getGender(); // undefined
```
## this はどこに指しているのか
>ma.myGender();

使ってる*this*は、**maというオブジェクト**を指しているが

>getGender();

使ってる*this*は、**windowというglobal variable**を指している

## なぜ指す先が変った
一言うと、**呼び出し元**に*this*は左右されるからです
ma.myGender()の呼び出し元：ma
getGender()の呼び出し元：window

# 解決策
## thisをキャッチする

```javascript
var ma = {
    name: 'ma',
    gender: 'male',
    myGender: function() {
    var that = this;
        function getGender() {
            return that.gender;
        }
    }
};
ma.myGender(); // 'male'
```
## apply()とcall()
apply()とcall()で*this* の指す先がコントロールできる、例えば、

```javascript

function getGender() {
    return this.gender;
}

var ma = {
    name: 'ma',
    gender: 'male',
    myGender: getGender
};

ma.myGender(); // 'male'
getGender.apply(ma,[]); // 'male'
getGender.call(ma); // 'male'
```
applyの第一引数は、*this*の指す先、第二引数がgetGender()のパラメータ配列(今回は[])
applyの第一引数は、*this*の指す先、第二引数がgetGender()のパラメータ(今回はなし)

## アロー関数

```javascript
var ma = {
    name: 'ma',
    gender: 'male',
    myGender: function() {
        var fn = () => this.gender;  // thisの指す先がmaオブジェクト
        return fn();
    }
};
ma.myGender(); // 'male'
```

アロー関数を使うと、

>var that = this;

という書き方がはいらなくなる

# まとめ
関数呼び出し側のオブジェクトが this になる
個人的にアロー関数でキャプチャされたときの this を保持する方法が一番見た目綺麗だと思う
ionic serve 時にno exported member 'Observable' エラー

ionicプロジェクトにてnpm install し、Angular6.0に更新されたところ、ionic serve でコンパイルエラー発生。

```
XXX/node_modules/rxjs/Observable"' has no exported member 'Observable'.
```

とnode_modules内で'Observable'がないと怒られる


```
npm install rxjs-compat --save
```

したら直った。(よくわかってないけどとりあえず解消したから先進む、、)
Unityでノベルゲームのように1文字ずつ表示する

こんにちは、今回はタイトル通りノベルゲームのように1文字ずつ文字を表示する簡単なやり方を説明します。

今回は本当に文字を出すだけで途中中断、文字色、サイズの変更などはひとまず考えずに説明します。
#準備
準備というほどでもありませんが2D表示用にCanvasとその中にTextのComponentがついているオブジェクトがあれば十分です。

#コード

```C#:NovelScript.cs
    [SerializeField] List<string> messageList = new List<string>();//会話文リスト
    [SerializeField] Text text;
    [SerializeField] float novelSpeed;//一文字一文字の表示する速さ
    int novelListIndex = 0; //現在表示中の会話文の配列

	void Start () {
        StartCoroutine(Novel());
    }
	
    
    private IEnumerator Novel()
    {
        int messageCount = 0; //現在表示中の文字数
        text.text = ""; //テキストのリセット
        while (messageList[novelListIndex].Length > messageCount)//文字をすべて表示していない場合ループ
        {
            text.text += messageList[novelListIndex][messageCount];//一文字追加
            messageCount++;//現在の文字数
            yield return new WaitForSeconds(novelSpeed);//任意の時間待つ
        }
        
        novelListIndex++; //次の会話文配列
        if (novelListIndex < messageList.Count)//全ての会話を表示したか
        {
            StartCoroutine(Novel());
        }
    }
```

これだけです。
コルーチン内部で文字を表示し全ての文字を表示し終わったら次の会話に行くというとてもシンプルなものです。

これを任意のオブジェクトに追加します。

今回は下記のような設定をしました。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/269147/261f416c-4013-0ae8-5d3f-0fec2feaf8e2.png)

3つの会話文、実際に表示するText、一文字一文字表示するスピード

これらを入力して実際に動かすとノベルゲームのように文字を表示できると思います。
![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/269147/1adfb671-34d7-9b0f-cc6e-004f9f3016fe.png)


#注意
今回は本当に簡単に文字を表示するものを作りました。

今回の問題点としては
・任意のタイミングで次の会話に移れない。
・一時停止ができない。
・会話のキャンセル（一括表示）ができない。

など多くの問題があります。
もし時間があれば次回、上記の問題の解決策を書いていこうかなと思います。



以上となります
見てくださったかた、ありがとうございました。
RailsアプリをPostgresqlを使って作成する効率的な方法

# はじめに
超初心者の私にわかりやすい、Rails newをする際のPostgresql設定情報があまりなかったため、こちらで研究したものを記述していきたいと思います。分かる方がいれば共有いただけると大変助かります。

# 設定環境
- OS
    - Mac OS X
        - 10.12.6
- Software
    - PostgreSQL
        - 10.1
    - Ruby
        - 2.5.0
    - Rails
        - 4.2.3

# ここでやりたいこと
Rails newの段階からPostgresqlのデータベースを使用し、テスト環境、本番環境合わせて、
以下のシンプルな３つの流れを実行できるようにしたいです。

**1. Railsアプリ作成時にPostgresqlを準備しておく**
**2. Postgresqlを使って開発をするための設定をする**
**3. Heroku上に問題なくDeployしてサービス公開する**


ローカル環境でpostgresqlを設定する方法はこちらを参考に調査中です。
[MacのRailsアプリでPostgreSQLを使う方法](https://qiita.com/yh2020/items/8be3087004d100fe752b#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
[Ruby on Railsの開発環境でPostgreSQLを利用する]
(https://qiita.com/taKassi/items/8e43171aeda300b67213)


→DB設定が先なのか、アプリ作成が先なのかわかりません。誰か知ってたら教えてください。。。


それでは順番に実行していきましょう。

# **Railsアプリ作成時にPostgresqlを準備しておく**

まずローカルで使えるPostgresqlのバージョンを確認する
psql --version
バージョンが確認できたら、自身のPostgresqlのリストを確認する
psql -l
そのあと自分でデータベースを作成する
createdb todo_development


# **Postgresqlを使って開発をするための設定をする**

これから先は現在確認中です。


# **Heroku上に問題なくDeployしてサービス公開する**

これから先は現在確認中です。



## 参考サイト
OpenposeのPYTHON API

# 概要
[OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)という骨格推定ができるOSSがめっちゃすごい！
さらに最近、本家にPython APIが実装されたみたいなので、試してみました。
Ubuntu 14.04.5 LTS(GPUあり）です。

# インストール
以下、`${HOME}/openpose_ws`というフォルダ以下をワークスペースとして説明します
なお、本記事執筆時点でのOpenposeのコミット番号は`7c21e0b6b184e4dd0b7e119f470089a4149b6e2d`です。


```bash
$ mkdir ${HOME}/openpose_ws
$ cd ${HOME}/openpose_ws
$ git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose
$ cd openpose
($ git checkout 7c21e0b6b184e4dd0b7e119f470089a4149b6e2d) # 必要であれば行ってください
$ mkdir build; cd build
$ cmake -DBUILD_PYTHON=true .. 
$ make -j5 # -j5 は自身の環境に合わせて変更してください
$ sudo make install
```

# 実行結果

```bash
$ cd {HOME}/openpose_ws/openpose/build/examples/tutorial_python
$ python 1_extract_pose.py
```

上記実行後、detectの結果と以下の画像が表示されればOK

![output_sample.jpg](https://qiita-image-store.s3.amazonaws.com/0/114699/1a447534-e2fb-31f2-406e-f7b6860929f9.jpeg)

# python実装についてのメモ
`1_extract_pose.py`の中身を少し見てみたので、メモです。
parameterの辞書を引数として`OpenPose`のインスタンスを生成し(37行目)、
`openpose.forward(image, display)` にて、結果を受け取る流れみたいです。
めっちゃ簡単ですね！

なお、`forward`関数の第一引数は、numpyarray, 第二引数の`display`は、OpenPoseで骨格推定結果を埋め込んだ画像を返り値に含めるかどうかのフラグです。
なので、keypointsの配列のみ欲しい場合は、43行目の部分を

`keypoints = openpose.forward(img, False)` 

と変更する必要有です。

以下、`1_extract_pose.py`の抜粋です。

```py
...
 22 params = dict()
 23 params["logging_level"] = 3
 24 params["output_resolution"] = "-1x-1"
 25 params["net_resolution"] = "-1x368"
 26 params["model_pose"] = "BODY_25"
 27 params["alpha_pose"] = 0.6
 28 params["scale_gap"] = 0.3
 29 params["scale_number"] = 1
 30 params["render_threshold"] = 0.05
 31 # If GPU version is built, and multiple GPUs are available, set the ID here
 32 params["num_gpu_start"] = 0
 33 params["disable_blending"] = False
 34 # Ensure you point to the correct path where models are located
 35 params["default_model_folder"] = dir_path + "/../../../models/"
 36 # Construct OpenPose object allocates GPU memory
 37 openpose = OpenPose(params)
 38
 39 while 1:
 40     # Read new image
 41     img = cv2.imread("../../../examples/media/COCO_val2014_000000000192.jpg")
 42     # Output keypoints and the image with the human skeleton blended on it
 43     keypoints, output_image = openpose.forward(img, True)
...
```

`OpenPose`クラスは、`${HOME}/openpose_ws/openpose/build/python/openpose/openpose.py`にて定義されているので、
もっと詳細が知りたい方は、こちらを確認してみてください。

# その他
python2(.7.6)およびpython3(.4.3)でも動作しました！
なお、`/usr/local/python/openpose`に必要なライブラリがインストールされるので、`PYTHONPATH`を、
インストール先フォルダに設定して、35行目の`params["default_model_folder"] = dir_path + "/../../../models/"`を
自身の環境に合わせて修正することが必要です。


# 参考
- [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)
【Fuel】FuelPHPフレームワークの初回構築手順

# はじめに
今更ながら、FuelPHPに関わることになり
今更ながら、**ローカル環境にてFuelPHP環境を構築する手順**を踏んでみた

# 環境
- Mac OS
- PHP 7.1　※インストール済み
- Fuel 1.8

# 手順
以下２通りの手順があり、

1. コマンドラインによるインストール
2. 手動によるインストール
	- GitHub から最新のリリースを clone する
	- GitHub から最新の開発ブランチを clone する

今回は **手動によるインストール** とする。
参考：http://fuelphp.jp/docs/1.8/installation/instructions.html#/from_github


## インストール
FuelPHPをGitHubから最新のリリースをcloneする。

```console
$ cd インストールしたいディレクトリ
$ git clone git://github.com/fuel/fuel.git .
```

## 設定ファイルの編集
インストールした`fuel/app/config/config.php`を以下のように設定する。

```php:config.php
'language' => 'ja'
'encoding' => 'UTF-8',
'default_timezone' => 'Asia/Tokyo',
'log_threshold' => Fuel::L_ALL,
```

参考：[アプリケーション設定](http://fuelphp.jp/docs/1.8/general/configuration.html)


## Composerの実行
```console
$ php composer.phar self-update
$ php composer.phar update
```

## パーミッションの設定
```
$ php oil refine install
```

## ビルトインサーバの起動
```
$ php -S localhost:8080
```

## その他
### 起動後アクセス
- welcomeページ 
http://localhost:8080/public/welcome

- helloページ 
http://localhost:8080/public/welcome/hello

### 進め方
- 流れの理解
	- [FuelPHP フレームワーク超入門](https://cloudear.jp/blog/?p=400)
- 仕組みを理解
	- [モデル、ビュー、コントローラ (MVC)](http://fuelphp.jp/docs/1.8/general/mvc.html)
	- [10分でわかるFuelPHP](https://www.slideshare.net/kenjis/20130413-fuel-phpintro)



 

# 参考
- 手順関連
	- [FuelPHPドキュメント](http://fuelphp.jp/docs/1.8/installation/instructions.html#/from_github)
	- [FuelPHPをインストールし、ビルトインサーバで動作させる](https://qiita.com/uchiko/items/a5c2e45264963acc0e4a)
	- [FuelPHP フレームワークをインストール](https://cloudear.jp/blog/?p=354)
	- [ざっくりFuelPHPの使い方](https://qiita.com/kazukichi/items/2a6e242091c5f485b976)
	- [FuelPHPをインストール](https://mynavi-agent.jp/it/geekroid/2017/10/fuelphp2.html)


- 問題解決関連
	- [FuelPHPのクイックインストールができない](https://qiita.com/amagurik2/items/d3fa36bead063d3b7f4b)
AWSのEC2で行うAmazon Linux2の初期設定

AWSのEC2で行うAmazon Linux2の初期設定です。<a href="https://aws.amazon.com/jp/about-aws/whats-new/2018/06/announcing-amazon-linux-2-with-long-term-support/" target="_blank" rel="noopener">Amazon Linux2が一般公開されました</a>ので、今後はAmazon Linux2で開発を行っていこうと思います。

> 従来のAmazon Linux は Amazon Linux 2 正式版のリリースより2年間、2020年6月30日まで最新バージョンに対するセキュリティ更新やサポートが提供されますので、2年の間にマイグレーションをご検討ください。
参考：[Amazon Linux 2 一般公開開始 と オンプレミス環境での実行について　 | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/amazon-linux-2/)

### バージョン情報
- [Mac OS](https://ninolog.com/about-my-mac/) 10.11.6（El Capitan）
- Amazon Linux 2 AMI (HVM)

#### 事前に用意しておく必要があるもの
- 接続先EC2のパブリックDNS
- 作業ユーザ（Amazon Linux2の場合デフォルトはec2-user）
- EC2からダウンロードした秘密鍵（デフォルトは****.pem）

#### その他情報
- Qiita:[AWSのEC2で行うAmazon Linux2の初期設定 - Qiita](https://qiita.com/2no553/items/e87485e3fc4199bd5dcb)

### AWSのEC2にSSH接続
秘密鍵を設定しAWSのEC2にSSH接続します。
#### 秘密鍵の設定

```
#EC2からダウンロードした秘密鍵を[ .ssh ]ディレクトリに移動
$ mv /Users/ユーザ名/Downloads/秘密鍵名.pem ~/.ssh/

#パーミッション変更
$ chmod 400 ~/.ssh/秘密鍵名.pem
```

#### ssh接続
```
$ ssh -i ~/.ssh/秘密鍵名.pem ユーザ名@パブリックDNS
Last login: Tue Sep 25 14:59:30 2018 from ***.***.ne.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
```

### 初期設定
必要に応じて初期設定を行います。

```
#パッケージ更新
$ sudo yum update -y

#パッケージ自動更新
$ sudo yum install yum-cron -y
$ sudo sed -i "s/^apply_updates.*$/apply_updates = yes/g" /etc/yum/yum-cron.conf
$ systemctl status yum-cron
$ sudo systemctl start yum-cron
$ sudo systemctl enable yum-cron

#タイムゾーン変更
$ timedatectl status
$ sudo timedatectl set-timezone Asia/Tokyo

#日本語ロケール追加
$ localectl status
$ sudo localectl set-locale LANG=ja_JP.UTF-8
$ sudo localectl set-keymap jp106
```

#### 不要サービス停止
GUIで不要なサービスの停止することもできます。

```
#不要サービス一括設定（GUI）
$ sudo ntsysv
```

##### 関連
- [AWSのEC2で行うAmazon Linux2（nginx・php\-fpm）環境構築 – Ninolog](https://ninolog.com/set-amazonlinux2-nginx-phpfpm-aws-ec2/)
- [AWSのEC2で行うAmazon Linux2（MySQL5.7）環境構築 – Ninolog](https://ninolog.com/install-amazonlinux2-mysql-aws-ec2/)

##### 参考
- [Amazon Linux - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html#extras-library)
Yamaha  RouterのLOGをMac OS X(high sierra)で受け取る

#概要
Yamaha ルータ(NVR500)のsyslogを Macで受信する設定方法

**おすすめの構成**
　Macのネットワーク構成でIPを固定設定
　有線LANで利用

**前提**
　Mac OS X（high sierra）
　ルータ　Yamaha NVR500

**手順概要**

1. MacのSIPをOffにする 
1. Syslogdの設定を変更 
1. ルータの設定

#MacのSIPをOffにする
 OS X 10.11 El Capitan以降では、セキュリティ機能(SIP:System Integrity Protection)が働き、Syslogdの設定変更をしても、「Operation not permitted」とエラーが発生し反映できません。この回避策です。

###リカバリーモードで起動
Macを再起動し、[Command+R]を押し続けて、リカバリーモードで起動
###ターミナルの起動
画面上部のメニューから[ユーティリティ]＞[ターミナル]を選択して、ターミナルを起動
###SIP状態表示
以下のコマンドで現在の「SIP」の状態を確認

```Terminal:Terminal
% csrutil status
System Integrity Protection status: enabled.
```

###SIP変更

```Terminal:Terminal
% csrutil disable
Successufully disabled System Integrity Protection. Please restart the machine for the changes to take effect.  
% reboot
```

###SIP状態表示
以下のコマンドで現在の「SIP」の状態を確認

```Terminal:Terminal
% csrutil status
System Integrity Protection status: disabled.
```

#Syslogdの設定を変更
###com.apple.syslogd.plistを編集用にコピー

```Terminal:Terminal
$ cd /System/Library/LaunchDaemons/
$ cp com.apple.syslogd.plist  /tmp
```

###plistはバイナリ形式なので、xml形式に変換し編集

```Terminal:Terminal
$ cd /tmp
$ plutil -convert xml1 com.apple.syslogd.plist 
# 追記内容は後述
$ vi com.apple.syslogd.plist 
```

###Syslog受信を設定
BSDSystemLoggerと同列になうように追記

```Terminal:com.apple.syslogd.plist
<!--
        Un-comment the following lines to enable the network syslog protocol listener.
-->
                <key>NetworkListener</key>
                <dict>
                        <key>SockServiceName</key>
                        <string>syslog</string>
                        <key>SockType</key>
                        <string>dgram</string>
                </dict>
        </dict>
</dict>
</plist>
```

###ファイルの修正を確認

```Terminal:Terminal
$ plutil -lint com.apple.syslogd.plist 
com.apple.syslogd.plist: OK
```

###バイナリ形式に変換して上書きコピーする

```Terminal:Terminal
$ plutil -convert binary1 com.apple.syslogd.plist
# 元の所に上書きコピー
$ sudo cp com.apple.syslogd.plist /System/Library/LaunchDaemons/com.apple.syslogd.plist
```

###ファイル書込みの設定とローテーション指定

```/etc/asl/NVR500-syslog (NEW file)
? [= Facility local1] [! Host <FQDN of localhost>] claim only
* file /var/log/NVR500.log mode=0644 rotate=seq compress file_max=1M all_max=50M 
```

###Syslogdの再起動

```Terminal:Terminal
$ sudo launchctl unload /System/Library/LaunchDaemons/com.apple.syslogd.plist
$ sudo launchctl load /System/Library/LaunchDaemons/com.apple.syslogd.plist
```

#Yamaha Router設定

```Terminal:Terminal
# syslog host [<host_ip>]
# syslog facility local1
# syslog notice on
```

#Consoleで確認
Application>ユーティリティ＞コンソール
コンソール起動後に左側の`/var/log`からNVR500.logで表示されていればOK

#参考記事
[EI Capitanでsudo付けているOperation not permittedが出た時の対処法](http://berukann.hatenablog.jp/entry/2015/12/30/123020)
[外部マシンのsyslogをMacで確認する](https://qiita.com/gm_kou/items/ee2ac91177468cd8e646)
[Mac OSXのsyslogでリモートからのログを別ファイルに保存する](https://gist.github.com/inouetmhr/87b5e3aa91c4d373c4e6)
[How to start Syslogd server on Mac to accept remote logging messages?](https://stackoverflow.com/questions/5510563/how-to-start-syslogd-server-on-mac-to-accept-remote-logging-messages/5518597)
vh, vwを使って上下左右中央揃えを実現する方法

個人的に結構クリビツテンギョウのK点超えだったので記録しておきたいと思います。

以前こちらのICS MEDIAさんの記事を拝見して「おーめちゃ便利や！」と思ったのですが、親要素のheightもついでに画面いっぱいにできればなあ…と考えておりました。結論を先に言うと、 **vh, vw**を使うとうまくできるようです。
**[上下中央揃えのCSSまとめ。Flexboxがたった3行で最も手軽](https://ics.media/entry/17522)**

簡単に意味について説明しておくと、以下のような値を持つプロパティです。

- vh … viewportのうちどのくらいの割合をheightとして持つか（1/100単位）
- vw … viewportのうちどのくらいの割合をwidthとして持つか（1/100単位）

vmaxがIE11でサポートしていない以外は、主要なブラウザでサポートされているプロパティです。
https://caniuse.com/#search=Viewport%20units

サンプルはCodePenに置いておきます。
<p data-height="665" data-theme-id="0" data-slug-hash="jpWKRp" data-default-tab="css,result" data-user="smartponzu" data-embed-version="2" data-pen-title="Centering elements without JS" class="codepen">See the Pen <a href="https://codepen.io/smartponzu/pen/jpWKRp/">Centering elements without JS</a> by FumiyaShibusawa (<a href="https://codepen.io/smartponzu">@smartponzu</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## 書き方
```scss

.foo {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
```
`height: 100vh;`を書くことによって、画面いっぱいに高さを確保することができます。これだけ！

### ※`position: absolute`を使うパターン
ちなみに冒頭のCodePenのサンプルでは、モーダルを表示するときの半透明のシャドウにもこのテクを使っています。`position: absolute`の場合、`top: 0;` `width: 100vw;`を明示的に指定して、左上端から画面いっぱいに表示幅を確保しています。

```scss
.foo {
  position: absolute;
  top: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw; // これを書くことでwidthも画面いっぱいに確保される！
}
```


## こんなとき便利

- Codepenとかで要素がはじっこにあるの嫌だから中央揃えしときたいとき
- モーダルを中央に表示したいとき


## 注意事項
`display: flex`を使うと当然子要素の振る舞いも変わります。ので、必ずしもこの方法が中央揃えを使うベストな方法とは限りません。

例えば`transform: translate(-50%)`を使う方法だってあるし、`display: table-cell; vertical-align: middle`や、`top: 0; left: 0; margin: auto;` の合わせ技とかもあったりします。ので、その時々にあったCSSを書くと幸せになれるかもしれません。