OmniAICreator/Qiita-1.07M huggingface dataset:
btcpay を自分のサーバにインストールする

### サーバを立ててドメインをDNSで紐付ける
 - 2GB RAM
 - 30GB storage

RAM と storageは可変にしておくこと。
以降、 testnet.btcpay.green をドメインとして説明

### ssh ログインしてgit をインストール
  省略

### btcpay をダウンロードしてフォルダに移動

```
sudo su -
cd /path/you/want/to/download/
git clone https://github.com/btcpayserver/btcpayserver-docker
cd btcpayserver-docker
```

### 各種環境設定

```
# testnet or mainnet
export NBITCOIN_NETWORK="testnet"

# どのコインを使うか
# 対応しているコイン一覧はこちら
# https://github.com/btcpayserver/btcpayserver-doc/blob/master/Altcoins.md
export BTCPAYGEN_CRYPTO1="btc" 

# lnd or clightning
export BTCPAYGEN_LIGHTNING="lnd" 

# 秘密鍵を作成してlet's encrypt でssl 設定
export ACME_CA_URI="https://acme-v01.api.letsencrypt.org/directory"
ssh-keygen -t rsa -f /root/.ssh/id_rsa_btcpay -q -P ""
echo "# Key used by BTCPay Server" >> /root/.ssh/authorized_keys
cat /root/.ssh/id_rsa_btcpay.pub >> /root/.ssh/authorized_keys
export BTCPAY_HOST_SSHKEYFILE=/root/.ssh/id_rsa_btcpay 
export BTCPAY_HOST="testnet.btcpay.green" # 自分のドメインに置換
export LETSENCRYPT_EMAIL="m@jiyu.green" # 自分のメルアドに置換

# ブロックを全部インストールすると容量を食いすぎるので減らす。
# 今回はlightning networkを使いたいので xs にした。
# testnet ではこのオプションは無効かもしれない（フルノードになる）
# その他のオプションはこちら
# https://github.com/btcpayserver/btcpayserver-docker#generated-docker-compose-
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-xs"

# 他の設定項目も見たかったら以下のコマンドで見られる
. ./btcpay-setup.sh
```

### btcpay をインストールして立ち上げる
```
. ./btcpay-setup.sh -i
```

### CPU を使いすぎないよう、80%の上限を定める（任意）
```
docker update btcpayserver_bitcoind --cpus ".8"
```

### 立ち上がったか確認
Your nodes are synching... というポップアップが出てるときはブロックの同期中。これが消えたら利用可能

### その他
 - 立ち上げたあとに動かなくなったら、容量かRAM の不足を疑う
 - [ここ](http://slack.btcpayserver.org/) に行くと親切なお兄さんたちが教えてくれます（英語）
Nuxt.jsにi18nを導入してみる

# i18nとは
> ソフトウェアを特定の地域の言語、仕様に縛られることなく、世界各国で共通して利用できるようにすることを意味する「Internationalization」を省略した表記方法。間の「18」は、単語の先頭の"I"と末尾の"n"の間にある文字の数を意味している。単語自体が長いために便宜的に使われる表記方法である。 
I18Nの例としては、利用文字コードを想定しない、あるいはあらゆる文字コードに対応する、時刻や日時の表示形式を任意に指定可能できるようにするといった機能を入れるといったことが挙げられる。 
日本語では「国際化」とも呼ばれる。 
>**Weblio辞書より**

# やってみよう
VueにはRuby on Railsのi18nのように書ける`vue-i18n`があるので、それを用いる。
また、SFC内にi18nを書くことが可能な`vue-i18n-loader`があるので、それも活用しようと思う。
※ yarnで書くので、npm使う場合は適宜読み替えてね

```
$ yarn install vue-i18n
```

```js:/plugins/i18n.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { getLanguage } from '~/utils/lang'

Vue.use(VueI18n)

export default ({ app, req, isClient }) => {
  // 標準はja
  let locale = 'ja';    
  if (isClient) {
　　　　　　　　　// SPAの場合
    locale = descriminationLang()
  } else if (req) {
　　　　　　　　// SSRの場合
    locale = req.headers['accept-language'].split(',')[0].toLocaleLowerCase().substr(0, 2)
  }
  app.i18n = new VueI18n({
    locale: locale || 'ja',
    fallbackLocale: 'ja'
  })
}

function descriminationLang () {
  const lang = getLanguage()
  // ない場合、日本語にする
  if (lang === undefined) return 'ja'
  if (lang.match(/en/)) {
    return 'en'
  } else {
    return 'ja'
  }
}

```

```js:/utils/lang.js
export const getLanguage = () => {
  const lang = (window.navigator.languages && window.navigator.languages[0]) ||
              window.navigator.language ||
              window.navigator.userLanguage ||
              window.navigator.browserLanguage
  return lang
}
```

※波線部分はデフォルトで書いてある記述とか自分で追記したものとかいろいろのこと

```js:nuxt.config.js
module.exports = {
~~
  build: {
    vendor: ['vue-i18n']
    ~~
  },
  plugins: ['~/plugins/i18n.js]
}
```

これで、i18nは動く。

### i18nをSFC内で書くための設定

```html:/pages/index.vue
<template lang="pug">
div
  p {{ $t('message') }}
</template>

<i18n>
en:
  "message": "Hello, i18n world!"
ja:
  "message": "こんにちは、i18nの世界！"
</i18n>

<script>
export default {

}
</script>
```

```js:nuxt.config.js
module.exports = {
~~
  build: {
    extend (config) {
      const vueLoader = config.module.rules.find((r) => {
        return r.loader === 'vue-loader'
      })
      vueLoader.options.preLoaders = vueLoader.options.preLoaders || {}
      vueLoader.options.preLoaders.i18n = 'yaml-loader'
      vueLoader.options.loaders.i18n = '@kazupon/vue-i18n-loader'
    },
    ~~
  }
}
```

これでSFC内でもi18nを**yaml**で書けるようになった(Railsっぽいなぁ)

# Vue.jsでやる場合
`vue-cli v3`から`vue-cli-ui`があるけど、それ専用のプラグイン`vue-cli-plugin-i18n`があるので、GUIで編集できるぽいからそれ使ってみてもいいかも。

# 参考
[**[Qiita]** nuxt.js で vue-i18n を使えるようにする](https://qiita.com/ooharabucyou/items/0e0801b4334edc761937)
[**[Qiita]** Nuxt.jsでいい感じにi18nを使う](https://qiita.com/takyam/items/4861badeb88dcee67d0a)
[**[Qiita]** javascriptでブラウザの言語設定を取得する](https://qiita.com/shogo82148/items/548a6c9904eb19269f8c)
SESのエンジニアに伝えたい7つのこと

# 今の私の状況とスキルセット

1月から在宅勤務でフルタイムでlaravelとVue.jsの開発をしていて業務委託契約（書面上の契約書は渡されていない）で月20万プラス税（深夜稼働あり）だったが5月に突然契約先から給与が額面通り払えないと言われて、致し方なく収入を保持するために業務委託契約のまま（さらに書面は渡されていない）SESで収入を得ている。

スキルセット的には
- PHP
- laravel fuel WordPress
- HTML5 CSS3
- JavaScript
- jquery
- AWSでのサーバ構築

# SESで絶対に自覚するべきこと

## 人の言葉を信じるな
- 商流を出来る限り把握して言葉をきくこと
- 営業は口ではエンジニアにも常駐先にも上手いこと言うがそれは嘘だと思うべき
- 常駐先がベンチャーで社長とか役員の言葉が直接聞ける状態で社員になれと言われてもSESの営業はそれを阻止する。もっと言えばあれは嘘でしたなんて常駐先から言われる


## いつ切られるかわからない
これはスキル不足が原因か、態度やモラルが原因か色々ある

- スキル不足
これは単純に自分のスキル不足が原因。
学習をしなかった自分が悪い。

- 勤怠不良
自己管理の問題。
体調管理も仕事のうち。
でも電車遅延についてもここに関わるから早めに会社に着くくらいの時間に家を出て適当にモーニングでも食べればいいと思う。

- モラルの問題
喫煙者なら喫煙所、お手洗いならそこのお手洗いのマナーを守る。
最低限の話。

- 女性のSESエンジニアに言えること
人間関係で揉めます。
絶対にマウンティングしてくるお局さんがいる。
致し方ない。
もっと言えばそれが人事だったり、プロジェクトリーダー以上の権限を持つ人間達の可能性がある。
うまくやらないと速攻で攻撃される。
-- 加筆 2021/07/20 あー、紅一点一匹狼になるとけむたがれるから男と対等になんて色々なっとさ。出る杭は打たれるし打たれたら終わり。

## 自分の値段を自覚しろ
これは言うまでもなく、自分の手取り収入イコール常駐先が自分の人件費を払ってる金額は全く違うよって話。
だいたい自分の手取り収入の3倍くらい常駐先がお金を払って自分を買ってると思った方がいい。

## どんなに業務ができても、常駐先の経営上で切られる

- 自社が切りたい人間をわざと赤字の会社に派遣する場合がある
- 業務ができてもプロジェクトの予算以上にSESを入れた場合切られる
- SESで行った先で自社が提示している金額、もしくは見積もりで出された金額以下で買われた場合、単価が高いものが優先されるので自社から撤退を言い出す。

## 長く居たいなら最低限の仕事をしろ。でも常駐先の社員にはなれない。
- 言われたことだけやる
これでなんとかエンジニアとしての居場所は作れる
- 長く居たとしても社員にはなれない。
労働基準法が云々したところで派遣先の経営状況が安定していなければ一年二年居てもいつ切られるかわからない。
- 実績を残したところで一時的評価であって、ただの消費対象でしかない自分を自覚するべき

## 常駐先を選べ
- 自分を伸ばせる場所か、どうかを見極める。
マニュアルで対応すれば問題ないです的な現場は単価も安いしスキルを伸ばせる機会が限られるのでお見送りする。
- 商流を考えろ
2次受けまでならなんとかだと思う。それ以上になると収入的にも額面は減るので自社が他の現場に移そうとし始める。
- 楽で高いところに行きたいなら同じSESをやってる企業でも大手と直接取引があるところを選べ

## 自分を伸ばしたいのなら常駐先で知り合ったエンジニアと親しくする。
これが一番大切かもしれない。
私が今一番支えられてるのはここ。
各々SESだったり社員だったり立場が違うから求められてる技術は各々異なっていて、
何か自分の中で問題が起きた時に相談ができる、相手が困ったら知恵を貸す、そういう循環が出来るので新しい技術も、古い技術も自分の知恵として得やすくなるし、業界の内情も見えやすくなる。

# エンジニアはエンジニアで仲良くhappy！になろう。
立場が違くても、エンジニア同士で楽しく過ごして、業務に繋がればhappy！
自分が辛くなった時に同じことSESの人に愚痴を言って話を聞いてもらえて心がすっきりすればhappy！
SESさんが困った時、何か手助けできればhappy！
常駐先にギャフンと言わせて退場出来ればhappy！


気軽に行こうぜ！
Amazon Connect

#■Amazon Connectとは？#
コンタクトセンターに必要なソリューションをALL in Oneで提供します。


#■コンタウトセンターの課題#

- PBX IVRなど専用機器の導入で初期費用が高額になる。
- 導入までのリードタイムが長くなる。
- 複雑なシステム構造のため、自社でメンテナンスや柔軟な機能拡張が困難。
- キャンペーン対応時などの一時的な伸縮性のシステムにかける。


#Amazon Connectと連携する主なAWSサービス**#

| サービス名      |  内容 |   
|:-----------------|:------------------|
| AWS Lamba |サーバをプロビジョニングしたり管理しなくても、コードを実行できるコンピューティングサービス|
|Amazon Polly|文章を音声に変換するサービス|
|Amazon Lex| 自動音声応答などとして利用できる |


#■特徴#

1.セルフサービスの設定と管理
これまで数ヶ月かかっていた構築をわずか数分で行うことができます。
↓のGUIのように容易に作成することができます。
![スクリーンショット 2018-10-03 22.45.35.png](https://qiita-image-store.s3.amazonaws.com/0/280929/568a1201-4973-14fc-156b-6b4b7fc8c4fa.png)

[Amazon Connect]() ハンズオンもぜひご覧ください。

2.ダイナミックなコンタクトフロー
個人を特定する、個人を特定したフローを実現していく。
↓CRM（過去の履歴など）を参照して、Amazon Pollyに文章を読ませる例です。
![スクリーンショット 2018-10-04 19.05.10.png](https://qiita-image-store.s3.amazonaws.com/0/280929/b424dba8-1da9-1dc0-1390-edb864f346ce.png)

3.オープンプラットフォーム
前に述べているAmazon Connectと連携する主なAWSサービス、AWS Lambaと連携したり、音声データをS3に保存したりすることができます。
↓Amazon Lexと連携して無人応答ができる例です。
![スクリーンショット 2018-10-04 19.21.34.png](https://qiita-image-store.s3.amazonaws.com/0/280929/f744f85f-4bb1-f4c5-4693-ee86401f6b57.png)

4.AWSのエコシステム
外部ツールと連携することができます。
↓SalesforceのCTI Adaptorとの連携の例です。
![スクリーンショット 2018-10-04 19.25.18.png](https://qiita-image-store.s3.amazonaws.com/0/280929/2569e11d-7d3d-a899-38d0-2f9ccb815a24.png)

[Amazon Connect ハンズオン](https://qiita.com/leomaro7/items/33850c149a01df51f879)もご覧ください。


#■利用料金#
初期投資は不要、利用した分だけの従量課金制
無料利用枠有り


#■アップデート情報#

https://aws.amazon.com/jp/about-aws/whats-new/2021/02/amazon-connect-now-provides-disconnect-reason-voice-calls-tasks/

[Feb 22, 2021]
CTRストリーム機能で、音声通話とタスクの切断理由が含まれるようになりました。
CTRには、お客様の状態や通話時間の情報が含まれます。
通話を切断したのはエージェントなのか顧客なのか、通話が切断されたのはテレコムまたはネットワークの問題なのか確認できるようになります。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-connect-supports-15-minute-intervals-for-historical-metric-reporting/

[Mar 1, 2021]
Amazon Connect は履歴メトリクスを 15 分間隔で表示できるようになりました。
今までは、30分間隔でした。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-connect-customer-profiles-now-supports-data-sources-from-amazon-s3/

[Mar 1, 2021]
Customer Profiles では外部アプリケーションで管理している顧客情報をAmazon Connect に取り込むことができるという機能になります。
今まで、Salesforce、ServiceNow、Zendesk、Marketoなどのサードパーティアプリケーションには対応していましたが、AmazonS3 をサポートしたということになります。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-connect-launches-new-metric-capabilities-for-measuring-queue-service-levels/

[Mar 17, 2021]
service level メトリクスを解析できるようになり、コンタクトセンターのパフォーマンスが、SLA通りか確認するのに役立ちます。
Karabiner-Elements でキーバインド変えたら、VIM 使ってる時に困った

## 何をしたか
- Karabiner-Elements で PC-Style Shortcut という Complex Modifications を適用した

## 何に困ったか（例）
- VIM 使っている時
	- `Ctrl+v` で短形ヴィジュアルモードに移行しなくなった
	- `Ctrl+v` でエスケープシーケンス送れなくなった
	- `Ctrl+a` `Ctrl+e` 等でカーソル移動しなくなった
- iTerm2 上で
	- `Ctrl+f` でカーソル移動しなくなった（検索窓が開く）

## どう対応したか
- `frontmost_application_unless` 使って PC-Style 適用アプリを iTerm2 以外にしよう
	- 元の JSON ファイルを変更し `.config/karabiner/assets/complex_modifications/` 以下へ下記例のような内容の適当なファイル名で配置

### 例：PC-Style Paste を iTerm2 には適用しない
```
{
  "title": "PC-Style Shortcuts(without iterm2)",
  "rules": [
    {
      "description": "PC-Style Paste(without iterm2)",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "v",
            "modifiers": {
              "mandatory": [
                "control"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "v",
              "modifiers": [
                "left_command"
              ]
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "^com\\.googlecode\\.iterm2$"
              ]
            }
          ]
        }
      ]
    }
  ]
}
```
JupyterでOpenCVを使うときにdestroyAllWindows()すると固まってしまう

# 問題
JupyterでOpenCVを使うときにcv2.destroyAllWindows()すると固まってしまう

# 環境
- macOS High Sierra
- Jupyter notebook
- OpenCV2

# 解決

```
cv2.startWindowThread()
cv2.imshow('image', img)
key = cv2.waitKey(0)

if key == ord('q'):            #qを押した時の処理
    cv2.waitKey(1)
    cv2.destroyAllWindows()
    cv2.waitKey(1)   
```

# まとめ
- imshowの前にstartWindowThread()を入れる
- destroyAllWindows()をwaitKey()で挟む

[参考にしたリンク](https://teratail.com/questions/107002)
SQLiteで改行コード

SQLite3想定です。2とか知らん。

改行コードと言えば、CRLF(Windows)と、LF単品(Windows以外)がありますね。
これを区別して表現したいってこと、あると思います。CRLFをLFに変換するとか、よくあることかと。

C言語とかのノリで'\r\n'とか書いて失敗した人、いるんじゃないでしょうか。
これ、SQLiteでは、文字通り、'\r\n'(バックスラッシュ・アール・バックスラッシュ・エヌ)です。

SQLiteで改行コードを表現するには、[char](https://www.sqlite.org/lang_corefunc.html#char)関数を使います。

```sql
SELECT
    char(13, 10) AS CRLF,
    char(10) AS LF
```

たとえば、Windowsの改行コードを滅ぼすには、次のようにします。

```sql
UPDATE my_table
SET my_value = replace(my_value, char(13, 10), char(10))
```

単に改行したいだけなら本当に改行するという手もあるんですが、こういう方法もあるということで。
ちなみに私は、ついうっかり'\n'(バックスラッシュ・エヌ)を入れてしまったテーブルを直すのに使いました。
フロントあんまり触らない人が「あれっCSS適用されないぞ？」と思った時に最初に見るべきこと

```html
<!-- 誤
<form class="form_group"></form> -->
<!-- 正 -->
<form class="form-group"></form>
```
スネークケース(単語の間を`_`で区切る)が標準の言語をサーバーサイドで使っていると、ついついCSSのクラス名もそのように記述してしまいますが、HTMLやCSSでは普通ケバブケース　(単語の間を`-`で区切る)が使われます。Bootstrapなどの著名なCSSフレームワークでもケバブケースが使われています。なんとなくドキュメントを読んだ記憶のままスネークケースでクラスを書くとなんのスタイルもつかないので注意しましょう。
(「そんなミスしないよ！」って思った方はごめんなさい。僕は二日に一回くらいするんです・・・)
Go初学者が学んだことまとめ〜appendがどのくらい遅いか検証してみた〜

#はじめに
Goの参照型であるスライス(可変長配列)は、appendすることで要素数を拡張できます。
しかし、容量をオーバーした場合、メモリ上のデータを新しい領域にコピーするという処理が走り、動作コストが高いとされています。
そこで、どのくらい実行性能に影響があるのか、実際にコードを書いて試してみました。

なお、appendの仕様はこちらにまとめてあります。
[Go初学者が学んだことまとめ〜その２〜（参照型）](https://qiita.com/haru_iwamoto/items/0c2d43b06f712311aa18)

#測定
Goのバージョンはこちら。

```
$ go version
go version go1.11 darwin/amd64
```

1万〜10億回、配列に値を格納する処理の実行時間を計測しました。
条件は下記の通り。

|関数名|型|初期の長さ|初期の容量|ループ処理|
|:--------|:--------|:---------|:-------|:-----------|
|sliceTime|スライス|0|0|append|
|allocatedSliceTime|スライス|0|1万〜10億|append|
|initializedSliceTime|スライス|1万〜10億|1万〜10億|代入|
|arrayTime|配列|1万〜10億|1万〜10億|代入|

検証コード

```Go:main.go
package main

import (
	"fmt"
	"time"
)

const maxLoopCount = 1000000000

func sliceTime(loopCount int) {
	beforeTime := time.Now()
	slice := make([]int, 0)
	for i := 0; i < loopCount; i++ {
		slice = append(slice, i)
	}
	afterTime := time.Now()
	diff := afterTime.Sub(beforeTime)
	fmt.Printf("slice time(loop %d):%s\n", loopCount, diff)
}

func allocatedSliceTime(loopCount int) {
	beforeTime := time.Now()
	slice := make([]int, 0, loopCount)
	for i := 0; i < loopCount; i++ {
		slice = append(slice, i)
	}
	afterTime := time.Now()
	diff := afterTime.Sub(beforeTime)
	fmt.Printf("allocated slice time(loop %d):%s\n", loopCount, diff)
}

func initializedSliceTime(loopCount int) {
	beforeTime := time.Now()
	slice := make([]int, loopCount)
	for i := 0; i < loopCount; i++ {
		slice[i] = i
	}
	afterTime := time.Now()
	diff := afterTime.Sub(beforeTime)
	fmt.Printf("initialized slice time(loop %d):%s\n", loopCount, diff)
}

func arrayTime() {
	beforeTime := time.Now()
	ary := [maxLoopCount]int{}
	for i := 0; i < maxLoopCount; i++ {
		ary[i] = i
	}
	afterTime := time.Now()
	diff := afterTime.Sub(beforeTime)
	fmt.Printf("array time(loop %d):%s\n", maxLoopCount, diff)
}

func main() {
	for i := 10000; i <= maxLoopCount; i *= 10 {
		sliceTime(i)
		allocatedSliceTime(i)
		initializedSliceTime(i)
	}
	//arrayTime() //maxLoopCountを10000〜1000000000に変更し、ビルドして実行した
}
```

#結果

実行時間

| loop|sliceTime|allocatedSliceTime|initializedSliceTime|arrayTime|
|:---------|:-------------|:--------------|:-------|:----------|
|10000|231.196µs|39.464µs|38.007µs|3.015µs|
|100000|2.349229ms|135.933µs|95.347µs|28.81µs|
|1000000|13.2845ms|1.303881ms|1.059979ms|278.565µs|
|10000000|109.442382ms|12.975474ms|13.98987ms|32.87561ms|
|100000000|1.313008414s|136.082698ms|135.611302ms|330.41205ms|
|1000000000|50.543104006s|9.616915173s|1.730548321s|3.340341675s|


容量0で毎回appendした場合(sliceTime)がダントツで遅いです。やはり容量の拡張は時間がかかる処理なのでしょう。

事前に容量の確保だけした場合(allocatedSliceTime)と、事前に容量の確保と初期化をした場合(initializedSliceTime）では、10億回ループを回すとようやく差が出てきました。
配列(arrayTime)とinitializedSliceTimeを比較すると、以外にもループの数が大きくなると、initializedSliceTimeの方が実行速度が速いという結果になりました。内部的にはどちらも固定長配列に値を代入しているだけだと思うのですが、何が違うのでしょうか。

全体的に見れば、事前に容量を確保したスライスと配列の速度はさほど変わりはないので、スライスと配列の選択をする際は、基本的に速度のことは意識せず、状況によって使いやすい方を使えばいいかと思います。

#まとめ
* 容量拡張が発生するappendはそれなりに実行性能に影響がでるので、スライスを使うときは、なるべく事前に容量を確保しておいた方がいい。
* 上記さえ気を付けていれば、スライスと固定長配列のどちらを使うか選択する場面では、実行性能のことはあまり意識しなくてもいい。

さて、この結論で正しいのでしょうか。

#関連
[Go初学者が学んだことまとめ〜その２〜（参照型）](https://qiita.com/haru_iwamoto/items/0c2d43b06f712311aa18)
ペグマン非表示

## GoogleMapsAPI のペグマン非表示

streetViewControl を設定


~~~
var mapOptions = {
  mapTypeControl: true, //マップタイプ コントロール
  fullscreenControl: true, //全画面表示コントロール
  streetViewControl: true, //ストリートビュー コントロール
  zoomControl: true, //ズーム コントロール
};
~~~
kaminari　使い方

#Gemfileに記入しbundle install


Gemfileに下記のように記入。

```
gem 'kaminari'
```

で
```$bundle install```


#一覧を表示しているコントローラに追記する

```
def index
    @messages = current_user.messages
  end
```

上記に```.page(params[:page])```をつけるのみです。

```
def index
    @messages = current_user.messages.page(params[:page])
  end
```

#一覧を表示しているビューに追記する

```<%= paginate @messages %>```
上記コード（この場合ではindexアクションに定義した@messages）を表示させたい場所に追記。

これで表示はできます。

#1ページに表示するレコード数を指定

***.per(5)***を追記するだけです。（この例だと、５つの投稿のみ表示ということ。）

```
def index
    @messages = current_user.messages.page(params[:page]).per(5)
  end
```

#bootstrap風にするには

```$rails g kaminari:views bootstrap3```

上記コマンドでOK.見た目がよくなります。
BigQuery — WITHはネストできる ( サブクエリの中に書ける )

書いてみたら出来た。

「WITH はサブクエリの変種なので、クエリ本体に書けるものなら何でも書けるんじゃないか」と理解した。「サブクエリ」というくらいだし。


改めて考えてみれば当たり前のような気もした。

## クエリ例

```sql
WITH result AS (
   WITH example AS ( SELECT * FROM `dataset.table` )
   SELECT * FROM example
)

SELECT * FROM result
```

## Public Dataset での例


```sql
WITH result AS (
   WITH games_wide_limitted AS ( SELECT * FROM `bigquery-public-data.baseball.games_wide` LIMIT 100 )
   SELECT * FROM games_wide_limitted
)

SELECT * FROM result
```

## 深いネストの例

```sql
WITH result AS (
   WITH reg_season AS (
     WITH  year_2016 AS (
       SELECT * FROM `bigquery-public-data.baseball.games_wide` WHERE year = 2016
     )
     SELECT * FROM year_2016 WHERE seasonType = 'REG'
   )
   SELECT * FROM reg_season
)

SELECT * FROM result
```

## Links

- [Gist](https://gist.github.com/YumaInaura/7f91a915d53bf4a63708a5605d4e1404)
- [Medium—Imported](https://medium.com/supersonic-generation/bigquery-with-clause-in-subquery-6d59a7474827)









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
webpackのmodule.rulesとmodule.loadersの違い


# 結論
module.rulesを使った方がいいらしい

# ソース
https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.23

> rules should be used instead of loaders, but the old one still work.

訳
> loadersの代わりにrulesを使うべき。でも、古い方もまだ動く

# まとめ
新しく投稿されているQiitaの記事でも、未だにmodule.loadersを使う記事があって、よくないと思った。日本語の記事なさそうだから、仕方ないけど。
TypeScript で関数合成やPipe処理をする

## はじめに

「関数合成」と聞くとなんだか難しいイメージがありましたが、
調べてみると初歩ならば私でも理解できる部分もあったので記事を書いてみます。
よろしくお願いします。

文字だけの場合、高階関数は型がある方が読みやすい[^1]と思ったので JS でなく TS を選びました。

## 関数を合成してみる

以下の「1を足す関数」と「２を掛ける」を合成します。

```ts
const add1 = (n: number) => n + 1
const times2 = (n: number) => n * 2

console.log(add1(5))  // 6
console.log(times2(5))  // 10
```

合成と言うとなんだか難しく聞こえますが、「関数を順に適用する」だけです。

```ts
// イメージ
console.log(add1(times2(5)))  // 11
```

次に『関数を合成して合成した関数を返す』関数を定義します。
`add1`と`times2`は数値を受け取って数値を返すので以下の関数を定義すればよさそうです。

```ts:２つ関数を受け取って合成した関数を返す関数
const compose = (
  a: (n: number) => number,
  b: (n: number) => number
) => (x: number) => a(b(x))

//js だと const compose = (a, b) => x => a(b(x))
```

では`add1`と`times2`を合成した関数を使ってみます。

```ts
// add1OfTimes2 の型は関数 (x: number) => number
const add1OfTimes2 = compose(add1, times2)
console.log(add1OfTimes2(5))  //=> 11 (5 * 2 + 1)
```

## パイプ処理

先ほどの`compose`は引数の数が２つに固定されているので任意の引数を取れるようにします。
ついでに、引数は前から順に適用される方が直感的なので、そこも直すと以下のようになります。

```ts
const pipe = (...fns: Array<(n: number) => number>) =>
  (n: number) => fns.reduce((v, f) => f(v), n)
```

`...`はスプレッド構文です。可変長引数を定義できます。
`arguments`オブジェクトでなく`Array`として扱えます。
`reduce`は配列の各要素に対して（左から右へ）関数を適用し、単一の値にします。
MDN の解説がわかりやすいです-> [Array.prototype.reduce](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)

さっそく`pipe`を使って見ます。

```ts
const add1 = (n: number) => n + 1
const times2 = (n: number) => n * 2

const enhancer = pipe(add1, times2)

console.log(enhancer(5))  // 12
// ↑ (5 + 1) * 2
```

引数を増やしたり減らしたりしてみます。

```ts
// 「３を引く関数」を追加
const minus3 = (n: number) => n - 3

const enhancer2 = pipe(add1, times2, minus3)
console.log(enhancer2(5))  // 9
// ↑ (5 + 1) * 2 - 3

// 引数なし
const identity = pipe()

console.log(identity(5))  // 5
```

## `Generics`を使って数値以外もパイプ処理できようにする

上記の`pipe`は「数値を受け取り数値を返す関数」しか引数に取れませんでした。
`Generics`を使って文字列やオブジェクトなどに対してもパイプ処理ができるようにします。

```ts
const pipe = <T>(...fns: Array<(t: T) => T>) =>
    (t: T) => fns.reduce((v, f) => f(v), t)
```

`T`は型引数です。使うときはコンパイラが推論可能であれば、型引数は省略できます。（今回も省略します。）
これで補完などエディタの支援を受けつつも動的言語のように柔軟に処理ができるようになりました。

ではジェネリックな`pipe`を文字列で使ってみます。

```ts
const addTitle = (s: string) => `Mr. ${s}`
const hello = (s: string) => `Hello ${s}!`
const greeting = (s:string) => `${s} Nice to meet you.`

const enhancer = pipe(addTitle, hello, greeting)
console.log(enhancer('Nossa'))  // Hello Mr. Nossa! Nice to meet you.
console.log(enhancer('Smith'))  // Hello Mr. Smith! Nice to meet you.

// もちろん今までのコードも動作します。
const enhancer2 = pipe(add1, times2, minus3)
console.log(enhancer2(5))  // 9
```

## 最後に

この記事では`pipe`や`compose`などの高階関数に渡す引数の関数を、一度ローカル変数として定義しました。
ラムダ式を直接渡すことももちろん可能です。

```ts
const greet = pipe(
  (s: string) => `Mr. ${s}`,
  (s: string) => `Hello ${s}!`,
  (s: string) => `${s} Nice to meet you.`
)
console.log(greet('Nossa'))  //=> Hello Mr. Nossa! Nice to meet you.
```

世間では React の HoC や redux、recompose といったライブラリで広く使われている関数の合成ですが、
私個人としては実務での使いどころを見いだせていません。
使いこなせるようになって副作用が少なくバグのないコードや、スコープが小さく脳内メモリに優しいコーディングがしたいです。
ここまで読んでいただきありがとうございました！！

[^1]: エディタで入力補完が効いて楽という点もあります。
Ubuntu 21.10 に Elasticsearch をインストール

Ubuntu のカーネル

```text
$ uname -a
Linux iwata 5.13.0-27-generic #29-Ubuntu SMP Wed Jan 12 17:36:47 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
```

Java のインストール

```bash
sudo apt install openjdk-11-jdk
```

Java のバージョン

```text
$ java --version
openjdk 11.0.14 2022-01-18
OpenJDK Runtime Environment (build 11.0.14+9-Ubuntu-0ubuntu2.22.10)
OpenJDK 64-Bit Server VM (build 11.0.14+9-Ubuntu-0ubuntu2.22.10, mixed mode, sharing)
```

Elasticsearch のインストール

```bash
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update
sudo apt install elasticsearch
```

サーバーの状態の確認

```bash
sudo systemctl status elasticsearch
```

サーバーの起動

```bash
sudo systemctl start elasticsearch
```

クライアントから、サーバーの確認

```text
$ http http://localhost:9200
HTTP/1.1 200 OK
X-elastic-product: Elasticsearch
content-encoding: gzip
content-length: 319
content-type: application/json

{
    "cluster_name": "elasticsearch",
    "cluster_uuid": "R92Wu-uxTl2gad2cs6OkIg",
    "name": "iwata",
    "tagline": "You Know, for Search",
    "version": {
        "build_date": "2022-03-17T22:01:32.658689558Z",
        "build_flavor": "default",
        "build_hash": "d0925dd6f22e07b935750420a3155db6e5c58381",
        "build_snapshot": false,
        "build_type": "deb",
        "lucene_version": "9.0.0",
        "minimum_index_compatibility_version": "7.0.0",
        "minimum_wire_compatibility_version": "7.17.0",
        "number": "8.1.1"
    }
}
```

クライアントからの確認は、こちら
[Elasticsearch の使い方](https://qiita.com/ekzemplaro/items/809baf4fb405ed4bcc9d)

## 立ち上がらない時の対策 ##

```text:/etc/elasticsearch/elasticsearch.yml
(省略）
xpack.security.enabled: false
```
Gutenberg で「更新できません」「無効なjson・・・」と表示された時の原因

# 結論

- Gutenberg は、REST API ( /wp-json 以下と通信 ） 使う
- WAFなどで、この通信を制限していると、エラーが起こる
- 対策は、この制限を解除すること

# 経緯

WordPress 5.0 から導入される新しいブロックエディタを気に入って使っています。投稿する人のモチベーションが上がって、とても良いです。執筆者が喜んで、使ってくれています。

しかし、エラーに悩まされることも、度々。

最近も、急にエラーがではじめたのですが、原因はWAFにありました。WordFenceという有名なWAFプラグインを利用していたのですが、Leanringモードから自動的に「Portectionモード」に切り替わったタイミングでエラーが起こりました。

特にわかりづらかったのが、「過去の投稿を編集できるけど、新しい編集はエラー」となったため、最初は混乱しました。調べてみると、WordFence が特定の投稿へのREST APIアクセスをWhiltelist として学習していたためです。

※ 親ディテクトリで、WordFence プラグインを使っていて、「サブディレクトリのWordPress」の wp-jsonへのアクセスがブロックされてしまいました

解決方法は、WAFの設定を見直すことです。

# WAF が動いていると考えられる場所を点検する

以下のような場所を点検して、適切に設定します。

- WordPressプラグインで、ブロックしていないか？ (WordFence）
- レンタルサーバーの設定で、ブロックしていないか？ (国外IPアドレスブロックなども)
- CloudFlare などの CDN でブロックしていないか？ (基本はしません)

例えば、レンタルサーバーで「国外IPからのブロック」となっていて、CloudFlareを使っていると、時々問題が起こるそうです。CloudFlare経由でのアクセスが、国外IPとして見える時があり、その時にエラーが起こります。

CloudFlare の Page Rule で、 wp-admin や wp-json は、Bypass 指定すると良いかもしれません。

# 原因の調査方法

エラーが発生したら「要素の検証」などを使って、エラーを見ます。すると、403エラーや、401エラーが多発していました。それらのURLをみると、wp-json 以下だったので、「WAFかも」と思い、WAFをしてそうなところを総点検して解決しました。


---

現役プログラマでも、システムエンジニアでもないので、情報が曖昧かもしれませんが、  参考になれば、幸いです
情報処理技術者試験 高度午前キーワード一覧


午前の思い出し。試験日まで随時更新します。

ネットワークは以下の記事でまとめています。

[ネットワークスペシャリストのキーワード一覧](https://qiita.com/estaro/items/e4432b66dc813ff45c6a)

## はじめに

情報処理技術者試験における高度区分の共通午前I問題に出題されるキーワードをまとめました。

午前Iについては合格点をとると2年間免除されるということもあって、忘れがちになるため一覧にまとめてみました。

ここでは私が自信のない内容についてのみ、まとめており、 **網羅性はありません** のでご注意ください。

## セキュリティ

- WAF

    - Web Application Firewall。Frameworkのことかと思った。WAFって言い方するみたい。


## 開発

- COCOMO
    - 見積モデル
    - 過去の開発から統計的に算出
    - コード行数
    - 使っているのを見たことないので覚えられない

- SOA
    - Service Oriented Architecture
    - SOXとごっちゃになってた

## ITIL関係

- サービスレベル管理
    - SLAの交渉・合意
    - 継続的なモニタリングと報告
    - 事前の予防策の提案

## 監査

- 独立性
- 基準
    - システム監査基準
    - システム管理基準
    - 情報セキュリティ監査基準
    - 情報セキュリティ管理基準
- 内部統制

## システム戦略・企画

- TCO(Total Cost of Ownership)
- BPO(Business Process Outsourcing)
- BABOK
- 共通フレーム2007
- グリーン購入法
- SWOT分析
- KGI, KPI
- CSF

## さいごに

## 参考
Kotlin/NativeマルチプラットフォームプロジェクトでiOSとAndroidでビジネスロジックを共有する

# 概要
Kotlin/Nativeを使えば、Kotlinで書いたビジネスロジックをiOSとAndroidで共有することができます。

[Xamarin](https://www.jmas.co.jp/xamarin/)などのクロスプラットフォームライブラリとは異なり、Kotlin/Nativeでは純粋なビジネスロジックのみ共有できるので、UIロジックはそれぞれのOSの言語やフレームワーク(iOSなら[Swift](https://swift.org/)と[UIKit](https://developer.apple.com/documentation/uikit))を使って実装することが出来ます。

# 公式チュートリアル
以下に公式のチュートリアルがあるので、その通りやればKotlinのコードをAndroidとiOSで共有する方法がわかります。

- [チュートリアル: Multiplatform Project: iOS and Android](https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html)

githubに[サンプルコード](https://github.com/JetBrains/kotlin-examples/tree/master/tutorials/mpp-iOS-Android)も上がっています。

# 参考

- [Kotlin 1.3-M2: new multiplatform projects model](https://discuss.kotlinlang.org/t/kotlin-1-3-m2-new-multiplatform-projects-model/9264/27)
- [Building Multiplatform Project on Kotlin/Native](https://shakuro.com/blog/building-multiplatform-project-on-kotlinnative/)
- https://www.kotlindevelopment.com/kotlin-multiplatform-in-action/

# サンプルコード(有用順)
- [JetBrains/kotlinconf-app](https://github.com/JetBrains/kotlinconf-app) : ktor, unit-test
- [armcha/KotlinMultiplatformTests](https://github.com/armcha/KotlinMultiplatformTests) : coroutine、ktor
- [russhwolf/ktor-demo](https://github.com/russhwolf/ktor-demo) : ktor, unit-test
- [gogabr/SpeechDetector](https://github.com/gogabr/SpeechDetector/blob/91cae9c6ac8bbab55c3023b8e3f222843801e804/speechdetection/build.gradle)
- [revolut-mobile/mobius_multiplatform](https://github.com/revolut-mobile/mobius_multiplatform/) : ktor
- [samus/mpp_chuck_demo](https://github.com/samus/mpp_chuck_demo) : ktor, unit-test
- [h0tk3y/k-new-mpp-samples](https://github.com/h0tk3y/k-new-mpp-samples)
Ubuntu Server 18.04LTS のインストールで詰まった件

# 概要
Ubuntu-server 18.04 のインストール中に apt でコケてしまい，インストールが中断されてしまった．
原因は apt が参照したサーバのエラーだったので，URL を変更することで解決した．
別に Ubuntu のインストール時に限らず起こることだが，インストール中に起こったときの解決方法はあまり存在しなかったので投稿．

# Ubuntu-server 18.04 の導入
IoT 用途で [StickPC](https://www.amazon.co.jp/dp/B00W7KAABK) にサーバ環境を構築したかった．
そこで [Ubuntu-server 18.04 LTS](http://cdimage.ubuntu.com/releases/18.04.1/release/?_ga=2.226685791.355767922.1538675096-1336540760.1537180389 "ubuntu-server installer") をインストール．

言語の設定，ネットワークの設定，ディスクパーティションの設定，ユーザの設定，を終えていざインストール．
しかし肝心のインストールが始まると，"An error has occurred" となり，"Installing kernel" の項目で止まってしまう．
詳細なログを見てみると，

> Err:1 http://220.152.35.158:80/data/.../archive.ubuntu.com/ubuntu bionic-security/main amd64 linux-modules-4.15.0-36-generic amd64 
> Redirection loop encountered

とあった．
仕方なく "Exit to shell" を選択し原因を探索．

# Shell からの作業
Ctrl+Alt+F2 を押すか，インストール失敗の画面で "Exit to shell" を押してターミナルを切り替える．
まずは apt 自体が正常に動くのかを確認する．

```shell
sudo apt update
sudo apt upgrade
```

ここでまたも同じエラーに遭遇．

```shell
sudo apt update --fix-missing
sudo apt upgrade
```

これでもだめ．
どうやら archive.ubuntu.com の調子が悪いようだ．

# 解決へ
Ubuntu インストーラの "Configure Ubuntu archive mirror" の設定で，apt が利用する URL をデフォルトの http://archive.ubuntu.com/ubuntu から http://ftp.iij.ad.jp/pub/linux/ubuntu/archive/ に変更．
別にどこでも良かったのだが，たまたま見た[このサイト](https://qiita.com/fkshom/items/53de3a9b9278cd524099 "apt-getの利用リポジトリを日本サーバーに変更する")を参考にさせてもらった．
[Official Archive](https://launchpad.net/ubuntu/+archivemirrors) から選んでみてもいいかもしれない．
abc 058　

B
すぬけ君は新しくできたプログラミングコンテストに会員登録しました。 登録に使ったパスワードを覚えておく自信が無かったすぬけ君は、 手元の紙にパスワードをメモしておくことにしました。 ただし、そのままメモをすると誰かにパスワードを盗まれてしまうかもしれないので、 文字列の偶数番目の文字と奇数番目の文字をそれぞれ別々の紙にメモしておくことにしました。
パスワードの奇数番目の文字だけを順番を変えずに取り出した文字列 O と、 偶数番目の文字だけを順番を変えずに取り出した文字列 E が与えられます。 すぬけ君のかわりにパスワードを復元してください。

```
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
	string O, E;
	cin >> O >> E;
	for (int i = 0; i < O.size(); ++i) {
		cout << O[i];
		if (i <= E.size() - 1)
			cout << E[i];
	}
	cout << endl;
	return 0;
}
```
よゆ

C
すぬけ君は、文字列の書かれた紙から文字をいくつか切り抜いて、並び替えて別の文字列を作るのが好きです。
明日になると、すぬけ君は文字列 S1,…,Sn のうちどれか 1 つが書かれた紙がもらえます。 すぬけ君は文字列を作る事をとても楽しみにしているので、どんな文字列を作るか計画を立てることにしました。 ただし、すぬけ君はまだどの文字列が書かれた紙がもらえるかを知らないため、 どの文字列が書かれていた場合にも作れる文字列を考えることにしました。
S1,…,Sn のどの文字列が書かれていても作れる文字列のうち、最長のものを求めてください。 最長のものが複数ある場合は、辞書順で最小のものを求めてください。

むず。

解説を読む。そりゃそうだってなる。やっぱキョウプロは柔軟に考えないと話にならねえ。。

```
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main() {
	int n;
	cin >> n;
	int b[30];
	for (int i = 0; i < 30; ++i) {
		b[i] = 100;
	}
	string S[51];
	for (int i = 0; i < n; ++i) {
		cin >> S[i];
		int a[30] = { 0 };
		for (int j = 0; j < S[i].size();++j) {
			int x = S[i][j] - 'a';
			a[x]++;
		}
		for (int j = 0; j < 26; ++j) {
			b[j] = min(b[j], a[j]);
		}
	}
	for (char i = 'a'; i <= 'z'; ++i) {
		for (int j = 0; j < b[i - 'a']; ++j) {
			cout << i;
		}
	}
	cout << endl;
	return 0;
}
```

何か月か後の自力ACコード

```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<iomanip>
using namespace std;
#define FOR(i, a, b) for (ll i = (a); i <= (b); i++)
#define REP(i, n) FOR(i, 0, n - 1)
#define NREP(i, n) FOR(i, 1, n)
using ll = long long;
using pii = pair<int, int>;
using piii = pair<pii, pii>;
const int dx[4] = { 0, -1, 1, 0 };
const int dy[4] = { -1, 0, 0, 1 };
const int INF = 1e9 + 7;
int gcd(int x, int y) {
	if (x < y)swap(x, y);
	if (y == 0)return x;
	return gcd(y, x%y);
}

template<class T1, class T2> void chmin(T1 &a, T2 b) { if (a>b)a = b; }

template<class T1, class T2> void chmax(T1 &a, T2 b) { if (a<b)a = b; }
template<class T>
void Add(T &a, const T &b, const T &mod = 1000000007) {
	int val = ((a % mod) + (b % mod)) % mod;
	if (val < 0) { val += mod; }
	a = val;
}
////////////////////////////////////////
int main() {
	int n;
	string S[51];
	int count[26];
	for (int i = 0; i < 26; ++i)count[i] = INF;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> S[i];
		int C[26];
		for (int j = 0; j < 26; ++j)C[j] = 0;
		for (int j = 0; j < S[i].size(); ++j) {
			C[int(S[i][j] - 'a')]++;
		}
		for (int j = 0; j < 26; ++j) {
			count[j] = min(count[j], C[j]);
		}
	}
	vector<char>V;
	for (int i = 0; i < 26; ++i) {
		while (count[i] != 0) {
			V.push_back(char('a' + i));
			count[i]--;
		}
	}
	for (int i = 0; i < V.size(); ++i) {
		cout << V[i];
	}
	cout << endl;
	return 0;
}
```
ParcelでTypeScriptを扱ったらES5になってしまうとき

- Parcel v1.10.1
- Node v10.11.0

Chromeで動けばいいアプリを、Parcelでbundleして出力を見たら、`var`と言っている

まず、Parcelは何でも屋。デフォルトでbabelを実行する。デフォルトの`browserslist`は`>0.25%`(!?)らしい。

無駄が多すぎるので`last 2 chrome versions`にしたが結果が変わらない。

# 原因
tsconfig.jsonが`"extends"`を使っていると、Parcelが解決できず、親のtsconfigにある`"target": "esnext"`を読んでくれない。

# 解決策

どうやら`"extends"`を諦めてコピペするしかなさそう・・・
https://github.com/parcel-bundler/parcel/pull/646

追記：
見てみたら簡単に修正できたのでPRを投げてみた
https://github.com/parcel-bundler/parcel/pull/2109
AWSで踏み台サーバーからプライベートサブネットのEC2にpecoを使って一発SSHする


以下の図のように、パブリックサブネットとプライベートサブネットを分けて、踏み台サーバー以外はプライベートサブネットに配置する構成はよくあると思います。
踏み台サーバーはEIPでグローバルIPを割り振ればいいのですが、プライベートサブネットに配置したEC2たち、しかもAutoScalingによってIPが不定のものに簡単にSSHしたかったので、少しスクリプトを組んでみました。

## 想定しているAWSの構成
![踏み台+EC2 ASG.png](https://qiita-image-store.s3.amazonaws.com/0/193814/4328c91e-461d-cfee-2799-bdf22bd01b45.png)


## プライベートサブネットのEC2には直接SSHは不可能

![SequrityGroup.png](https://qiita-image-store.s3.amazonaws.com/0/193814/ecc5c01c-ea78-28c0-debc-86fcc8f6207a.png)


# 一発で2段SSHするためのコマンド

以下のfunctionを `~/.config/fish/config.fish` に追加してください。

fishシェルのfunctionを定義しているので、bashやzshの方は適宜読みかえて下さい。
`aws`コマンドは`--profile`や`--region` を明示しているので、ここも適宜変更して下さい。
踏み台サーバーと対象サーバーでSSH鍵が異なる場合、1つ目の`$key`に踏み台用の鍵、 2つ目の`$key`に対象サーバーのSSH鍵を指定するように書き換えて下さい。

```sh
function ec2-ssh-myaws
  echo "ec2-user" | read -l user
  echo "~/.ssh/myaws.pem" | read -l key
  aws --profile myaws ec2 describe-instances --region ap-northeast-1 --output json --filters "Name=network-interface.group-name,Values=Bastion" | jq -r '.Reservations[].Instances[] | .PublicIpAddress' | read -l bastion
  echo "bastion server $bastion"
  aws --profile myaws ec2 describe-instances --region ap-northeast-1 --output json --filters "Name=instance-state-code,Values=16" | jq -r '.Reservations[].Instances[] | [.Tags[] | select(.Key == "Name").Value][] + "\t" +  .InstanceType + "\t" + .PrivateIpAddress + "\t" + .Platform' | awk '{if ($4 != "windows") printf "%-45s %-15s %-10s\n",$1,$2,$3}' | sort | peco | command awk '{print $3}' | read -l host
  echo "target server $host"
  ssh -o ProxyCommand="ssh -i $key -p 22 $user@$bastion -W $host:22" -i $key -p 22 $user@$host
end
```

追加し終えたら、次のようにfunctionを呼び出すだけで、プライベートサブネットにいるEC2の一覧が表示されて、選択したサーバーに繋がります。

```
ec2-ssh-myaws
```

# functionがやっていることの説明

1. 踏み台サーバーにEIPを割り振っていなくても対応できるように、踏み台サーバーのPublic IPを`aws`コマンドで取得
2. 起動中EC2の一覧を取得して、選択しやすいように整形してからpecoに渡す
3. 踏み台サーバーと選択した対象サーバーの情報でSSH

# 終わりに

この設定を使って楽をし始めた矢先に次の様な記事が公開されました。

[SSH不要時代がくるか!?AWS Systems Manager セッションマネージャーがリリースされました!](https://dev.classmethod.jp/cloud/aws/ssm-session-manager-release/)

AWS Systems Manager セッションマネージャーがあれば今回の設定は不要かもしれないですね。

# 参考リンク

* [pecoとEC2 APIを使って踏み台経由のSSHログインを楽にする](https://blog.jicoman.info/2018/04/ec2-ssh-using-peco/)
* [AWSで踏み台の先にあるEC2にタグでsshする](https://www.karakaram.com/aws-ssh-through-bastion)
Nuxt開発時に詰まったところメモ

# 概要
Nuxt2で開発してる時に詰まったところメモ

こちらを見る前に、
[Nuxt.jsの本格導入で遠回りしないためのTips v1.1
](https://qiita.com/devneko/items/afe12b8acaf9648ccbb6)
が詰まりやすいところまとまってるので確認すること。

## クライアントとサーバでAPIアクセスするURL変えたい
こちらにオプションがある。
https://axios.nuxtjs.org/options#browserbaseurl

```
axios: {
  baseURL: 'http://localhost:3000',
  browserBaseURL: 'https://testsite.jp',
  proxyHeaders: true
}
```

https://axios.nuxtjs.org/options#proxyheaders
proxyHeaders を追加すると、SSRの時に、header情報が送られる。
Cookieを送ることができるので、API側で、下記みたいな感じにCookie取得できるはず。

```
cookies = request.headers["Cookie"].split('; ').map do |cookie|
  cookie.split('=')
end.to_h
```

## componentの中でnoscriptを使いたい

JSオフの時に、アラート出すみたいな感じでnoscriptタグ使いたい時がある。
issue内にある通り、``nuxt.config.js``に追加すればできる。
https://github.com/nuxt/nuxt.js/issues/2582

あるいは、``app.html``を作って、デフォルトのテンプレートに、noscriptタグをhtmlに書いてもできた。
https://ja.nuxtjs.org/guide/views/

## storybookを使いたい
https://qiita.com/k-okada/items/afe442f7b328fb0041e1
みたいにしたら使えた。

下のように、全体を読み込むcss変数を設定した場合、
https://ja.nuxtjs.org/api/configuration-build/#styleresources

```nuxt.config.js
build: {
  styleResources: {
    scss: './assets/stylesheets/variables.scss'
  }
}
```

こんな風にstorybookのconfigファイルを変更するとエラーが起きない。

```.storybook/webpack.config.js
{
  test: /\.scss$/,
  loaders: [
    "style-loader", "css-loader", "sass-loader",
    {
      loader: "sass-resources-loader",
      options: {
        resources: [
          path.resolve(__dirname, '../assets/stylesheets/variables.scss')
        ]
      }
    }
  ],
},
```


## SSRしたい時、どの処理をどこに書けばいいの？
[図解](https://ja.nuxtjs.org/guide#%E5%9B%B3%E8%A7%A3)
![nuxt-schema.png](https://qiita-image-store.s3.amazonaws.com/0/72886/336b00a0-ec8d-1af0-20db-416771b5f3ec.png)

nuxtのssrするときの流れは上みたいな感じ。

- nuxtServerInit
    - serverアクセス時に一度しか呼び出されない。
    - 認証機能の時によく使われるとのこと
- middleware
    - ルーティングした後に、最初に呼ばれる
    - 全体のmiddleware、layoutのmiddleware、Pageのmiddlewareの三種類設定できる。
    - userAgentに関するデバイス判定処理とか、ログインしてるかしてないかでページ分けるとかする。
- validate
    - 動的なルーティングを行う際に、パラメータによってvalidateするのに使う
    - storeのデータを使ってvalidationも可能
    - fetchより先に呼び出されるから、APIから取得したデータをfetch()で、storeに入れる方法はできない。
    - その場合は、[エラー処理](https://ja.nuxtjs.org/guide/async-data/#%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86)の方法を使う
- fetch
    - SSR時に、APIから取得した情報とかをstoreに入れたい時使う
- asyncData
    - SSR時に、Dataを設定したい時に使う
    - fetchとasyncDataは出来ること一緒だけど、storeに入れたいか、dataとして使いたいかで使い分けるといいらしい
    - [Nuxt.jsのasyncDataとfetchの違いについて](https://zen-web.net/blog/nuxtjs-asyncdata-fetch/)

## あったらどんどん追記
[Julia] 多引数関数の速度比較

# 概要
物理計算などでは、計算ルーチンに多数のパラメータを渡すことがある。

パラメータの関数への渡し方として、

- 全部引数で直接渡す
- 構造体にまとめて1つの引数で渡す
- 辞書型リストで渡す

などの方法があると思われるが、Juliaでは速度の面でどの方法が良いか試してみる。

追記（2018/10/05）：
コメントをもらってやり直した結果、違う結論になったので、まとめなおしました。
[[Julia] 多引数関数の速度比較　その２](https://qiita.com/Yoshinobu-Ishizaki/items/ca2aeeb1024a0cd89934)
↓のは計算内容にちょこちょこ不具合あります。

# 比較

## 引数渡し

```julia:julia
function f(x::Real,y::Real,z::Complex=zero(Complex),
           temper::Float64=24.0)
    # dummy calculation
    for i in 1:100000
        z = complex(x,y) + temper
    end
end

@btime f(1,2.5)
    2.575 ns (0 allocations: 0 bytes)
```
引数の何番目が何なのか、という点でちょっと読みにくいけど、
~~結局、実はこれが一番速い。~~←ウソ、ではないけど最適化でループ回ってなかったようで数字が不当でした。

## 構造体渡し

```julia:julia
mutable struct St
    x::Real
    y::Real
    z::Complex
    temper::Float64
end

function f2(s::St)
    # dummy calculation
    for i in 1:100000
        s.z = complex(s.x,s.y) + s.temper
    end
end

st1 = St(1,2.5,0+0im,24.0)

@btime f2(st1)
  410.769 ms (700000 allocations: 22.89 MiB)

```

すごく遅い。

## 辞書リスト渡し

```julia:julia
dct = Dict(:x=>1,:y=>2.5,:z=>0+0im,:temper=>24.0)

function f3(d::Dict{Symbol,Number})
    # dummy calculation
    for i in 1:100000
        d[:z] = complex(d[:x],d[:y]) + d[:temper]
    end
end

@btime f3(dct)
  29.091 ms (300000 allocations: 9.16 MiB)

```

まぁ遅い。

# まとめ

ごく普通に引数で渡せってことですね。
ループの中で構造体メンバーや辞書リストメンバーにアクセスすると、そのオーバーヘッドが大きい、と。

まぁそうだろうなとは思いますが、速度差がここまでとは。。。

# マシンスペック

```julia:julia
versioninfo()

Julia Version 1.0.1
Commit 0d713926f8 (2018-09-29 19:05 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: AMD E2-3000M APU with Radeon(tm) HD Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, generic)
```
Firestore で、DB設計を考える際に参考になった情報

# Firestore におけるDB設計

DB設計について考える場合、そもそもFirestoreのようなドキュメント指向のNoSQLデータベースではどんなDB設計をするべきなのか、いろいろと情報を漁ってみました。

以下は、いろいろ調べた中で、個人的に参考になった記事です。
おそらくFirestore のDB設計について考える場合、今回挙げた記事は、何度も読むことになりそうなので、備忘録的に残すことにしました。

## NoSQLデータモデリング技法

https://gist.github.com/matope/2396234

### 参考になった点
- Firestore に限定されず、NoSQLデータベースとしてのプラクティスが網羅されている
- いきなり具体例ではなく、概念から解説してから、具体的な技法について解説している
- RDBでは、基本的には、正規化を徹底するが、NoSQLデータベースでは、非正規化を許容する、むしろ活かす

## Firestore Database Design

- https://speakerdeck.com/1amageek/firestore-database-design


### 参考になった点
- Firestore にフォーカスしている
- Firestore の基本的なデータモデルの概念であるコレクションとドキュメント・サブコレクションについて、図だけで十分伝わる
- Firestore を使った場合の開発の特徴(Client Side Join) についての言及している
- リレーションを Firestore ではどのように表現するか具体的なクエリ共に解説されている
- セキュリティルールについて取り上げている
- データの冗長化について取り上げている


## Cloud Firestoreの勘所 パート2 — データ設計

- https://medium.com/google-cloud-jp/firestore2-920ac799345c

### 参考になった点

- ブログサービスというかなり具体的な例を用いて、設計について解説しているのが超絶わかりやすかった
- 上２つの記事を読んで、事前情報を知った上で、再度読むとより理解が深まった

## Get to know Cloud Firestore

- https://www.youtube.com/watch?v=v_hR4K4auoQ&list=PLl-K7zZEsYLluG5MCVEzXAQ7ACZBCuZgZ

Firebase公式のYouTubeチャンネルです。

### 参考になった点

- 安定安心の公式の情報源というだけでなく、RDBと比較して、Firestore について、しっかり解説をしている
- 全て英語ですが、字幕もあり、動画内で説明用に出る図もわかりやすい

## Cloud Firestore Data Modeling (Google I/O'19)
- https://youtu.be/lW7DWV2jST0

こちらもFirebase公式の動画。

### 参考になった点
- FirebaseのYoyuTube公式チャンネルにて、Firestore の解説動画を担当されている方のセッション
- Firestoreが、正式リリースされてから半年以上は経った上で、改めてFirestore におけるデータモデリングのあり方を教えてくれる。
- 図解を交えて、非正規化で重複したデータが存在する状況で、どうデータ整合性を担保するかを解説してくれている
Axios(vue.jsのajax)で外部APIをたたく時のクロスドメイン問題を（サクッと）解決したメモ

#問題
####Vue.js（フロントエンド）から外部の(一部の)APIを呼び出す際、クロスドメインの制限でレスポンスを使えなくなってしまう。

###Q.そもそもなぜこんなことになっているのか
A.セキュリティの問題でそのWebアプリケーションのドメインのサーバとしか通信できないという**ブラウザ**の制約があるため。

##対策
調べたところ色々な対策が存在するようです。詳しく理解したいorしっかりと問題を解決したい方は[こちら等](https://tsmatz.wordpress.com/2011/06/24/jsonp-cross-domain/)をご参照下さい。

今回は少しずるい方法でサクッと解決したのでその覚え書きです。
##今回の解決法
この制約、**ブラウザに付いている**ため、サーバーサイド等からは通常通りAPIを利用することが可能です。
そこで適当なPHPの動くサーバー（筆者はlolipopのサーバーがあったので）にAPIを叩いてその値をそのまま返すphpを設置しました。

```
<?php
$url = 'APIのアドレス';
$json = file_get_contents($url);
header("Access-Control-Allow-Origin: *");
print $json;
?>
```

これで同じアドレスから取得したものを永遠に返せるphpが出来ました。あとはこのphpをaxiosで呼べば帰ってくるのは目的のデータです。
ポイントは `header("Access-Control-Allow-Origin: *");` で、このレスポンスはどこからでも使えるよヘッダーを付けています。

今回は行いませんでしたがアクセス先のAPIを動的に変更することもphpにURLを渡すだけなのでカンタンです。

####※この方法はセキュリティの問題によるブラウザの制限を迂回しています。試すなら自己責任でお願いいたします。
もうすこし簡単に解決する方法もあれば教えていただけると幸いです。
abc 057

B
xy 平面があり、その上に N 人の学生がいて、M 個のチェックポイントがあります。
i 番目の学生がいる座標は (ai,bi)(1≦i≦N) であり、番号 j のチェックポイントの座標は (cj,dj)(1≦j≦M) です。 
これから合図があり、各学生はマンハッタン距離で一番近いチェックポイントに集合しなければなりません。 
2つの地点 (x1,y1) と (x2,y2) 間のマンハッタン距離は |x1−x2|+|y1−y2| で表されます。
ここで、|x| は x の絶対値を表します。
ただし、一番近いチェックポイントが複数ある場合には、番号が最も小さいチェックポイントに移動することとします。
合図の後に、各学生がどのチェックポイントに移動するかを求めてください

```
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	int N, M;
	cin >> N >> M;
	int a[51], b[51], c[51], d[51];
	for (int i = 0; i < N;++i) {
		cin >> a[i] >> b[i];
	}
	for (int j = 0; j < M; ++j) {
		cin >> c[j] >> d[j];
	}
	for (int i = 0; i < N; ++i) {
		int min_dist = abs(a[i] - c[0]) + abs(b[i] - d[0]);
		int checkpoint = 1;
		for (int j = 1; j < M; ++j) {
			const int cur_dist = abs(a[i] - c[j]) + abs(b[i] - d[j]);
			if (cur_dist < min_dist) {
				min_dist = cur_dist;
				checkpoint = j + 1;
			}
		}
		cout << checkpoint << endl;
	}
	return 0;
}
```

C
整数 N が与えられます。 
ここで、2 つの正の整数 A,B に対して、F(A,B) を「10 進表記における、A の桁数と B の桁数のうち大きい方」と定義します。 
例えば、F(3,11) の値は、3 は 1 桁、11 は 2 桁であるため、F(3,11)=2 となります。 
2 つの正の整数の組 (A,B) が N=A×B を満たすように動くとき、F(A,B) の最小値を求めてください。 

```
#include<iostream>
#include<algorithm>
using namespace std;

int scale(long long a, long long b) {
	int acount = 0; int bcount = 0;
	while (a > 0) {
		acount++;
		a /= 10;
	}
	while (b > 0) {
		bcount++;
		b /= 10;
	}
	return max(acount, bcount);
}
int main() {
	int ans = 1e9;
	long long N;
	cin >> N;
	for (long long i = 1; i <= N; ++i) {
		for (long long j = i; j <= N; ++j) {
			if (i*j == N) {
				ans = min(ans, scale(i, j));
			}
		}
	}
	cout << ans << endl;
	return 0;
}
```
TLE...


交換法則を利用する


```
#include<iostream>
#include<algorithm>
using namespace std;

int scale(long long a, long long b) {
	int acount = 0; int bcount = 0;
	while (a > 0) {
		acount++;
		a /= 10;
	}
	while (b > 0) {
		bcount++;
		b /= 10;
	}
	return max(acount, bcount);
}
int main() {
	int ans = 1e9;
	long long N;
	cin >> N;
	for (long long i = 1; i*i <= N; ++i) {
		if (N%i != 0) 
			continue;
		else 
			ans = min(ans, scale(i, N / i));
	}
	cout << ans << endl;
	return 0;
}
```
treeコマンド

# お題
`history`コマンドに続き、気が向いたので`tree`コマンドについても少し戯れてみる。

# 実践

```
$ tree
.
├── README.md
└── src
    ├── main
    │   ├── chap01
    │   │   └── Main.java
    │   ├── chap02
    │   │   ├── Main.java
    │   │   └── foo.txt
    │   └── stream
    │       ├── Main.java
    │       ├── PgLang.java
    │       ├── PgLangFactory.java
    │       └── S.java
    └── test
```

## ■「.」ファイルも含めて表示

```
$ tree -a
.
├── .git
│   ├── COMMIT_EDITMSG
│   ├── FETCH_HEAD
│   ├── HEAD
│   │  〜省略〜
│   ├── objects
│   │   ├── 07
│   │   │   └── 15ce3de7c9837b35bccdb3f2f4dffdae1d9318
│   │   │     〜省略〜
│   │   ├── info
│   │   └── pack
│   │       ├── pack-a59346cd0f4da08405f4337d80b81d90b0e4559b.idx
│   │       └── pack-a59346cd0f4da08405f4337d80b81d90b0e4559b.pack
│   ├── packed-refs
│   └── refs
│       ├── heads
│       |  〜省略〜
│       └── tags
├── .gitignore
├── README.md
└── src
    ├── main
    │   ├── chap01
    │   │   └── Main.java
    │   ├── chap02
    │   │   ├── Main.java
    │   │   └── foo.txt
    │   └── stream
    │       ├── Main.java
    │       ├── PgLang.java
    │       ├── PgLangFactory.java
    │       └── S.java
    └── test
```

## ■ディレクトリだけ表示

```
$ tree -d
.
└── src
    ├── main
    │   ├── chap01
    │   ├── chap02
    │   └── stream
    └── test
```

## ■各ファイルのパスごと表示

```
$ tree -f
.
├── ./README.md
└── ./src
    ├── ./src/main
    │   ├── ./src/main/chap01
    │   │   └── ./src/main/chap01/Main.java
    │   ├── ./src/main/chap02
    │   │   ├── ./src/main/chap02/Main.java
    │   │   └── ./src/main/chap02/foo.txt
    │   └── ./src/main/stream
    │       ├── ./src/main/stream/Main.java
    │       ├── ./src/main/stream/PgLang.java
    │       ├── ./src/main/stream/PgLangFactory.java
    │       └── ./src/main/stream/S.java
    └── ./src/test
```

## ■表示階層を絞る

```
$ tree -L 2
.
├── README.md
└── src
    ├── main
    └── test
```

## ■フィルタして表示

```
$ tree -P M*
.
└── src
    ├── main
    │   ├── chap01
    │   │   └── Main.java
    │   ├── chap02
    │   │   └── Main.java
    │   └── stream
    │       └── Main.java
    └── test
```
フォーマット文字列で、整数を「2進数ゼロ詰めn桁」で表示する

#フォーマット文字列
RustやPythonでは、フォーマット文字列を使って、複雑なフォーマット指定で整数や浮動小数点数などを表示させることができます。
例えば、フォーマット文字列に `{:0>8b}` を使うと「2進数ゼロ詰め8桁」が実現できます。今回は、このフォーマットの `8` の部分を変数に置き換えたい、という話をします。

なお、Pythonの場合は、フォーマット文字列を動的に作ることができるので、このへんの話を覚えるよりも、`("{:0>" + str(n) + "b}").format(...)` とした方が楽かもしれません。
けど、一応、静的なフォーマット文字列でもできるということでご紹介します。

**とてもつらいことに、RustとPythonで、これを実現するためのフォーマット文字列は異なります**

#Rustの場合
```rust:Rust
fn main() {
    let kazu = 15;
    let keta = 6;
    println!("{:0>haba$b}", kazu, haba = keta);
    // または、以下でも可
    println!("{:0>1$b}", kazu, keta);
}
```

`:0>` に続けて、パラメータ名を指定し、`$`で区切ってから、表示形式を指定します。
そんなのどこに書いてあったのか、という話ですが。[ここらへん](https://doc.rust-lang.org/std/fmt/#syntax)を頑張って読むと書いてあります。幅だけじゃなく、浮動小数点数の精度も同じく、引数の番号または名前の後に`$`を付けるとパラメータを指定したことになる、と分かります。

#Pythonの場合
```py:Python
kazu = 15
keta = 6
"{:0>{haba}b}".format(kazu, haba=keta)
# もしくは
"{0:0>{1}b}".format(kazu, keta)
# これでもよい
"{:0>{}b}".format(kazu, keta)
```

ドキュメントのBNC記法っぽいものを眺めても、あまりピンとこないのですが、BNC記法じゃないところに「ネストできるよ」と書いてありました。そして[例として載ってました](https://docs.python.org/3.3/library/string.html#format-examples)。
さらには、こんな闇みたいなこともできます。

```py:闇フォーマット
# {:>012x}と同じ
"{:{}2{}}".format(10, ">01", "x")
```

便利ですね♪
PHP初心者らしく、まんまとforeachの参照ではまった

# はじめに

PHPに慣れた人ならばなんだ、そんな事かと思うくらいには有名な罠だが、まんまとはまったので個人の備忘録程度にメモ

同じような記事がごろごろあるあれです。

# 問題のコード

```php:
<?php

$ar = [1, 2, 3];
foreach($ar as &$elm)
{}

foreach($ar as $elm)
{}

var_dump($ar);
```

特に何かしたわけでもないがforeachを1回目は参照渡しで2回目はコピーで使用している。
この出力は以下である。

```php:
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(2)
}
```

チーン

# 原因
ブロックスコープがないphpでは1回目のforeachで宣言した$elmがループを抜けた後も生きており、配列の最後の要素の参照をもったままになっている。

そのため2回目のforeachでは

```php:
// $elmは$ar[2]を指しているので
$ar[2] = $ar[0]; // 1
$ar[2] = $ar[1]; // 2
$ar[2] = $ar[2]; // 2
```

といった挙動が発生してしまう。

# 対策

個人的には少しダサいと感じるがちゃんと`unset`

```php:
<?php

$ar = [1, 2, 3];
foreach($ar as &$elm)
{}
unset($elm);

foreach($ar as $elm)
{}

var_dump($ar);
```

出力

```php:
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
```

初心者の僕みたいな人は、例外などなくunsetを必ずする癖をつけたほうがよさそうだ

# まとめ

foreachで参照渡しした時、unsetを必ずしよう。

# 参考
http://php.net/manual/ja/control-structures.foreach.php
linuxパーミッション

# 技術知識

## netstat

## linux パーミッション
linux や unixのファイルやディレクトリのアクセス権を表すものです。

### 3つの項目
* 所有ユーザ


そのファイルやディレクトリの所有するユーザのことです。
その人のものなので基本的にはフルアクセスにします。

* 所有グループ


そのファイルを所有するグループ

* その他のユーザ

上記二つ以外のユーザの権限
[Swift] DataをData.imageでUIImageとして扱う方法(extensionの使い方)

# はじめに
どうもTOSHです！

プログラミンングを教えていて、`UIImageView`に対し、`.image`をつけると、UIImageとして扱えるのはご存知の通りなのですが、どうも、型の概念が分かっておらず、`Data型`のものに対しても`.image`をつけて、`UIImage`に変更している人がいたのですが、その時、`extension`使えばできるんじゃねと思ってやってみることにしました

# extensionとは

`extension`は今ある機能を拡張するということで理解をしているが、厳密にはどんな感じなんだろうと思って調べてみました。

```
そもそもカテゴリとは、既存のクラスにメソッドを追加するというのが目的であったのに対し、extensionでは、以下のような機能の拡張が可能です。

・計算プロパティ（クラス、構造体に対して）
・タイププロパティ
・メソッド
・subscript
・イニシャライザ(初期化子)
・ネストされた型
・ プロトコルに対する準拠
```
参照：https://www.sejuku.net/blog/33334

ウンウン、みた感じ可能そうではある。（あんまりこのような使い方をしないのかもしれないが...)
# やってみた
そもそも、Data型をUIImageに変更する場合は以下の通りである

```swift
var data: Data!
let image: UIImage = UIImage(data: data)
```

まあシンプルではあるが、今回の目的はextensionを使ってみることにあるので書いてみる

```swift
extension Data {
    var image: UIImage {
        let imagedData = UIImage(data: self)
        return imagedData!
    }
}
```
imageを定義してあげたので、これでうまくいくはずである。
これでやってみると

```swift

var data: Data!
        
let image: UIImage = data.image
```
で実際に、うまく動きましたとさ。

終わり