OmniAICreator/Qiita-1.07M huggingface dataset:
GooglePlayの累計ダウンロード数を知る方法

[GooglePlayConsole](https://play.google.com/apps/publish/) は日々進化しており、次々と新しい機能が実装され便利になっています。その半面、以前は表示されていた情報が表示されなくなるなど不便に思う点もあります。
特に**累計ダウンロード数**は多くの開発者にとって大きな関心事のはずですが、仕様変更により表示されなくなってしまいました。**累計ダウンロード数**より**アクティブなユーザー数**を重視するべきという考えはその通りだと思いますが、別に表示してくれてもいいじゃん！ってほとんどの開発者が思っていると思います。
知っている方も多かもしれませんが、実は[Google Play Consoleのアプリ](https://play.google.com/store/apps/details?id=com.google.android.apps.playconsole)を使うと今でも**累計ダウンロード数**を知ることができます。

### 累計ダウンロード数の表示方法

1. [Google Play Consoleのアプリ](https://play.google.com/store/apps/details?id=com.google.android.apps.playconsole)をインストールします。

2. 累計ダウンロード数を知りたいアプリを選択します。
![device-2019-03-04-224420.png](https://qiita-image-store.s3.amazonaws.com/0/30511/dd5cd026-8379-dadc-b56a-515463cd8692.png)

3. インストールユーザー数の[詳細を表示]をタップします。
![device-2019-03-04-224443.png](https://qiita-image-store.s3.amazonaws.com/0/30511/e05ebfbf-2de0-88f6-1fae-d468cde9a67e.png)

4. 表示するデータの期間を[全期間]に変更します。
![device-2019-03-04-224500.png](https://qiita-image-store.s3.amazonaws.com/0/30511/e9b4e873-8277-86f9-c7bf-ffd0104a9a7a.png)

5. グラフの上部に表示されるのが**累計ダウンロード数**になります。(多分)
![device-2019-03-04-224522.png](https://qiita-image-store.s3.amazonaws.com/0/30511/14dfb310-aca0-3d7c-c983-e9561a481a85.png)
Windows Subsystem for Linuxインストール手順


# はじめに
２回目でWindows Subsystem for Linuxをインストールした時もGoogleから始まりましたので、手順をメモしておきます。  
まだ、今回インストールしたのはUbuntu 18.04 LTSです。

# 環境
Windows 10 バージョン１８０９

# 手順

## Windows Subsystem for Linux機能の有効化  
- 管理者権限でPowershellを起動  
  左下のWindowsアイコンを右クリックし、「Windows PowerShell(管理者)」をクリックします。  
- 下記Windows Subsystem for Linux機能の有効化コマンドを実行します。  

  ```powershell
  Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  ```
- Windows再起動  
  再起動するかが聞かれますので、Yキーを押して再起動します。

## Ubuntuをインストール
- 「Microsoft Store」を起動し、「Ubuntu」を検索します。
- 「Ubuntu 18.04 LTS」を開きます。
- 「入手」をクリックすると、自動的にダウンロードされます。　
- ダウンロード完了通知が来ましたら、「起動」をクリックします。  
  起動したら、下記内容が表示され、ユーザー名とパスワードを入力してインストールを完了します。  

  ```bash
  Installing, this may take a few minutes...
  Please create a default UNIX user account. The username does not need to 
  match your Windows username.
  For more information visit: https://aka.ms/wslusers
  Enter new UNIX username: user
  Enter new UNIX password:
  Retype new UNIX password:
  passwd: password updated successfully
  Installation successful!
  To run a command as administrator (user "root"), use "sudo <command>".
  See "man sudo_root" for details.

  user@t303ua:~$
  ```

- ubuntuの更新  
  下記コマンドでubuntuを更新します。パスワードが聞かれますので、上記入力したパスワードを入力します。
 
```
sudo apt update
sudo apt upgrade -y
```

# 参考資料
- [Windows Subsystem for Linux Installation Guide for Windows 10](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)
sympyで(微分)「2019 神戸大学 前期日程 数学（理科系）1.(1)」 をやってみたい

読売新聞
https://www.yomiuri.co.jp/nyushi/sokuho/k_mondaitokaitou/kobe/mondai/img/kobe_zenki_sugaku_ri_mon.pdf
https://sokuho.yozemi.ac.jp/sokuho/k_mondaitokaitou/13/kaitou/img/kobe_zenki_sugaku_ri_kai.pdf
wolframalpha
log(x)/x
https://www.wolframalpha.com/input/?i=log(x)%2Fx
max{log(x)/x} = 1/e at x = e

```fullscript.py
from sympy import *
x = symbols('x', real=True)
f = symbols('f', cls=Function)
f=log(x)/x
eq=f.diff(x,1)
v = solve(eq)
print("v=",v[0])
print(f.subs(x,v[0]))
# v= E
# exp(-1)
```
インフォグラフィックスを制作するときに気をつけていること

先週、京都の島津製作所内にて開催されたインフォグラフィックス・ワークショップに、ファシリテーターとして参加しました。自分なりにいくつか気づきがあったので振り返って記載します。
内容は、自分でインフォグラフィックスを作成する際に、絶対に忘れてはならないと思う事をあらためてまとめた事なのですが、参加者の方にも何か参考になれば幸いです。

# ２重に危うい構造
あなたがインフォグラフィックスを作成するとき、あなたはアウトプットをより「わかりやすく」するために、元になるデータの中から意味を見つけようとして積極的に何らかの情報を抽出します。
抽出された情報は、元のデータ全体からすればあくまでも一部であり、必ずしも元のデータ全体の傾向と一致するとは限らない。一致するかもしれないし、反対のこともあるかもしれない。ちょっと関係があるだけかもしれないし、無関係な部分が大半かもしれない。
こうした元のデータ全体との関係性は、わかりやすさを重視するインフォグラフィックスの最終的なアウトプットからは隠されていて、見るだけではうかがい知ることが難しい。これがひとつ目の危険です。
次に、たくさんあるデータの中から、意味を見出し、誰かに気づかせるために抽出したのは、あくまであなたの主観であるということ。データにもとづいた客観性をうたいながら、積極的な主観の関わりがなくては成立しないという点。これがふたつ目。

この２重の危険性を持つインフォグラフィックスを作るとき、モラルという言葉の意味が私にはとても重く感じられます。
# 主観の必要性
そんな事を考えていると、どうにも気の重い気分になる時があります。
しかし、この主観をもって現実へ分け入る作業は、インフォグラフィックスを作成する際には、どうしてもしなければならないと私は思うのです。

例えば、あるニュータウン地域でまちづくりのためにアンケートを取りました。
その回答の集計結果をを地域の住民へ共有するとします。
どんな情報を共有すべきか、データーから意味を探します。
居住者の満足度は全体に高いのですが、一戸建てよりマンションの方が高い。
そしてマンション住人の方が、地域との関わりが少なく、個としての生活により満足している姿が浮かび上がるとします。他にこれからも長く地域に住みたいと考えてる人は、自治会を重要視し、地域の祭りに参加し、見守り活動に関心があると答えた人と相関関係があるとします。その他色々な分析があります。
ここで一戸建てとマンションの対比を強調するインフォグラフィックスはそれはそれで興味深いのですが、まちづくりのテーマから考えると不適切です。いたずらに対立を煽り分断が進むだけになるかもしれません。
それよりも、地域の自治活動にコミットメントの高い人間の方が、長く地域に住みたがっているという情報を楽しく発信すべきだと私は考えます。その方が地域の継続的な発展につながるかもしれないと思うからです。

元社会部の新聞記者で後にノンフィクション作家として活躍された本田靖春さんの評伝でも、事実と主観について書かれていて興味深かった。ノンフィクションも同じなんだなと思いました。
> そもそもノンフィクションは書き手の「主観」のもとに成立する。仮に、十人のノンフィクション作家が同一の出来事に取り組んだとすれば、十通りの作品が生まれる。事実の取捨選択からして「人生観、ないしは社会観、ひいては世界観、歴史観といった主観に基づいて」行われるからだ。「言い換えるならば、一遍のノンフィクションは出来事に仮託した書き手の存在証明ということになるのであろう」（「拗ね者たらん」後藤正治　本田靖春著作からの引用）

インフォグラフィックスが新聞報道の世界で育った事を思うと感慨深いものがあります。

# 事実と主観の分離
インフォグラフィックスを作成しているときに、最近私が特に注意しているのは、事実と主観をしっかり分離して描くということです。
上述のしたようにインフォグラフィックスは主観的な側面が強いので、できるだけ情報そのもので意図を表現するようにと考えています。

文章でも、事実にもとづいて記述しているつもりが、つい途中から自分の願望が混じってしまうことがありますよね。
同じようにデザインでも、不要な誇張、事実に相反する要素の混入、レイアウトの都合によるちょっとしたごまかし等はこれを頑として避けるべき。全体のトーンを調整するイラストレーションやエレメントは主観の表現なのでOK。でも、わかりやすくしようとしすぎたり、面白くしようとしすぎたりして、事実から導かれる値とは異なる図にしてしまうことは、頑なにこれを避ける。

主観に立脚している表現だから、この境界線を超えるのは簡単なんですが、事実と主観はきっちり分離して表現したいと苦闘しています。

あと、当然、間違い、勘違いも残らずなくすように校正を丁寧に行う事は重要です。
読者との信頼関係構築にはケアレスミスがないことがまずは大切。
Vueで直接DOMノードを参照するプロパティを知ってｱﾊ体験したのでまとめてみた

今日、Vueのコードを書いていて、ふと `vm.$el` の存在を思い出して猛烈に感動しました。
なので、Vueインスタンスから特定のDOM要素を参照できる方法を一覧してみようと思います。
~~ちなみに、途中までプロパティセレクタを使ったquerySelectorで、リストの特定要素を指定して意図通りに動いたものの……という顔をしてました~~

基本的に公式ドキュメントの [API — Vue\.js](https://jp.vuejs.org/v2/api/index.html) に書いてあることの引用です。

# 知ってマジ神だなって奴
## vm.$el - コンポーネントのルートDOMを得る
https://jp.vuejs.org/v2/api/index.html#vm-el

> 型: Element
> Vue インスタンスが管理している ルートな DOM 要素です。

```hoge.vue
<template>
  <div class="hoge">
    <p v-on:click="click">hoge</p>
  </div>
</template>

<script>
default export{
  methods:{
    click(){
      // <div class="hoge"> の DOM が入る
      console.log(this.$el) 
    }
  }
}
</script>
```

## vm.$refs - 子DOM/子コンポーネントを得る
https://jp.vuejs.org/v2/api/index.html#vm-refs
> 型: Object
> ref 属性によって登録されたDOM 要素のオブジェクトとコンポーネントインスタンスです。

公式ドキュメントの [特別な属性 - ref](https://jp.vuejs.org/v2/api/index.html#ref) と併せてお読みください。

```html
<!-- vm.$refs.p は DOM ノード -->
<p ref="p">hello</p>

<!-- vm.$refs.child は child-component のインスタンス -->
<child-component ref="child"></child-component>
```

とのことなので、どこにrefをつけるかで返り値が変わるようです。
ドキュメントにもありますが、レンダリング後に`vm.$ref`の値が入るようなので、この値が存在しなくてもエラーにならないようにハンドリングしてあげる必要があります。

# 一応できるやつ
## vm.$parent - 親コンポーネントを得る
https://jp.vuejs.org/v2/api/index.html#vm-parent
> 型: Vue instance
> 現在のインスタンスが1つ持つ場合は、親のインスタンスです。

親コンポーネントのインスタンスが返ります。 先程の`vm.$el`と組み合わせれば、親インスタンスのDOMノードが取得できますね。
まぁ、親のコンポーネントを操作するのはよほど密結合なコンポーネント同士でないと御法度でしょう。

```vue
 
<script>
default export{
  methods:{
    click(){
      this.$parent.$el // 親コンポーネントのルートなDOM要素
    }
  }
}
</script>
```

# slotを使うなら使いそうなやつ
## vm.$scopedSlots
https://jp.vuejs.org/v2/api/index.html#vm-scopedSlots

> 型: { [name: string]: props => Array<VNode> | undefined }
>プログラム的にスロットにより配信されたコンテンツにアクセスするために使用されます。各名前付きスロット は自身に対応するプロパティを持ちます (例: slot="foo" のコンテンツは vm.\$slots.foo で見つかります)。default プロパティは名前付きスロットに含まれない任意のノードを含みます。

とりあえず現状自分がSlotを使わなさそうなので詳細については調べてません。

#今回の要件ではあまりマッチしなさそうなもの
## vm.$root
https://jp.vuejs.org/v2/api/index.html#vm-root
> 型: Vue instance
> 現在のコンポーネントツリーのルート Vue インスタンスです。現在のインスタンスが親を持たない場合、この値はそれ自身でしょう。

概ね`vm.$parent`と似たような使用感覚だと思うのですが、コンポーネントツリーのルートを取得しても Element 取得の用途ではあまり役に立たなさそうです。

## vm.$children
https://jp.vuejs.org/v2/api/index.html#vm-children
> 型: Array<Vue instance>
> 現在のインスタンスの直接的な子コンポーネントです。
>\$children に対して順序の保証がなく、リアクティブでないことに注意してください。あなた自身、データバインディングに対して \$children を使用するためにそれを見つけようとする場合、子コンポーネントを生成するために配列と v-for を使用することを検討し、正しいソースとして配列を使用してください。

順序の保証がないというのは恐ろしいのでElementの取得用途では使いづらそうです。

# まとめ
リストレンダリングされたコンポーネントの自分自身のエレメントを取得するときに良かったです。

~~また、動的にstyle計算するのに現在のDOMから値を取得したものを算出プロパティの計算に使うと、~~
~~現在のDOMの状態をリアルタイムに反映した値を作ることができると思います。~~
生DOMの値はリアクティブに参照できなかったデス。

値の参照用途として、VueインスタンスからDOM要素を直接参照する方法を知っておくのはかなり役立つのではないでしょうか。


## 余談
### 親のDOMがほしい
単に親DOMがほしいときは `Element.parentNode` で取れます
https://developer.mozilla.org/ja/docs/Web/API/Node/parentNode

### 子や孫のDOMが欲しい
DOM要素に対してもquerySelector が使えるので、先に絞り込んでその中から取得することもできます。
https://developer.mozilla.org/ja/docs/Web/API/Element/querySelector
PowershellでMattermost APIを使ってみた時のメモ

# はじめに
お堅い会社でSlackとか使えず、でもみんなで使えるチャットが欲しく今更ながら担当でMattermostを導入してみた
で、今更お気に入りのPowershellでAPIをたたいてみた時のメモ。コピペしてIPアドレスとかを変更すれば試せるかと思います
（いい加減な人間なのでエラーハンドリングとかは適当です）

# ユーザ情報を取得する
ログインIDとパスワードを使ってトークンを取得し、さらに/usersの情報をGET
ConvertFrom-Jsonを使えば、取得したデータの利活用がめっちゃラク

```powershell
$ipaddress = "<Mattermostサーバ>"
$port = "<Mattermostサーバポート番号>"
$apiversion = "v4"
$loginid = "<ログインID>"
$password = "<パスワード>"

$uri = "http://" + $ipAddress + ":" + $port + "/api/" + $apiversion
$loginendpoint = $uri + "/users/login"
$usersendpoint = $uri + "/users"
$logindata = @{"login_id" = $loginid; "password" = $password}

# ログイン
$json_login = ConvertTo-Json $logindata
$res = Invoke-WebRequest -Uri $loginendpoint -Method Post -Body $json_login
if($res.StatusCode -ne "200"){
    Write-Debug "Statusが" + $res.StatusCode + "のため終了"
    exit
}
# トークンを取得
$token = $res.Headers.Token
$res = ""
# 現在の状況を確認する
$res = Invoke-WebRequest -Uri $usersendpoint -Method Get -Headers @{"Authorization" = "Bearer $token"}
# 文字コード変換
$con = [System.Text.Encoding]::Utf8.GetString([System.Text.Encoding]::GetEncoding("ISO-8859-1").GetBytes($res.Content))
# PSCustomObjectに変換
$users = ConvertFrom-Json $con
# 1人目のIDを抽出する
Write-output $users[0].id
```

### 動かしてみてわかったこと
* APIリファレンス読めばすぐわかるが、APIアクセス負荷を軽減するため、同時アクセス制限（RateLimit）が設定されているので注意
　途中でStatus500のInternal Server Errorが返って？？？となっていた
* これもAPIリファレンス読めばすぐわかるが、一度に取得可能なユーザ数はデフォルトで60となっている。

# 各ユーザのステータスを表示させる
各ユーザのステータス（プレゼンス情報）を取得して、大型ディスプレイに在席一覧を表示させるなどに使えそう

```powershell
$ipaddress = "<Mattermostサーバ>"
$port = "<Mattermostサーバポート番号>"
$apiversion = "v4"
$loginid = "<ログインID>"
$password = "<パスワード>"

$uri = "http://" + $ipAddress + ":" + $port + "/api/" + $apiversion
$loginendpoint = $uri + "/users/login"
$usersendpoint = $uri + "/users"
$logindata = @{"login_id" = $loginid; "password" = $password}

# ログイン
$json_login = ConvertTo-Json $logindata
$res = Invoke-WebRequest -Uri $loginendpoint -Method Post -Body $json_login
if($res.StatusCode -ne "200"){
    Write-Debug "Statusが" + $res.StatusCode + "のため終了"
    exit
}
# トークンを取得
$token = $res.Headers.Token

# 現在の状況を確認する
$res = Invoke-WebRequest -Uri $usersendpoint -Method Get -Headers @{"Authorization" = "Bearer $token"}
# 文字コード変換
$con = [System.Text.Encoding]::Utf8.GetString([System.Text.Encoding]::GetEncoding("ISO-8859-1").GetBytes($res.Content))
# PSCustomObjectに変換
$users = ConvertFrom-Json $con

# ユーザのステータスを抽出する
$usersstatus = @{}
foreach($user in $users){
    $statusendpoint = $usersendpoint + "/" + $user.id + "/status"
    $res = Invoke-WebRequest -Uri $statusendpoint -Method Get -Headers @{"Authorization" = "Bearer $token"}
    $con = [System.Text.Encoding]::Utf8.GetString([System.Text.Encoding]::GetEncoding("ISO-8859-1").GetBytes($res.Content))
    $status = ConvertFrom-Json $con
    $usersstatus.Add($user.username, $status.status)
}
# ユーザのステータスを表示する
$usersstatus
```

### 動かしてみてわかったこと
* 同じく高頻度でアクセスするとRateLimitに引っかかるので適度にスリープを入れる必要がある

# おわりに
POST、PUT、DELETE系もいくつか試したので、落ち着いたら更新します
Kerasを使ってμ's(2年生)の分類(1)

#概要
　スマートフォンアプリ「スクールアイドルフェスティバル(以下「スクフェス」)」のカードから学習データの作成を行いニューラルネットワークでの学習を行う．
　今回はその中で学習データの作成を行った．

#学習データ
　今回作成したデータは~~スクショが面倒だったため~~2年生の3人のみを対象とした．

- スクショにより得られた枚数
   - 高坂穂乃果:45枚
   - 南ことり:32枚
   - 園田海未:55枚

![スクリーンショット 2019-03-04 17.44.36.png](https://qiita-image-store.s3.amazonaws.com/0/323592/8a06feb8-7b04-9294-7248-a2e6b3a4c9a6.png)

　ニューラルネットワークでの学習を行うにあたり，これでは学習データが少なすぎると考えられるためDataAugmentationを行うことにした．

#DataAugmentation
　DataAugmentationとは画像の回転や拡大・縮小，左右反転を行うことによりデータの拡張を行うものである．
　KerasではImageDataGeneratorクラスを使うことによりDataAugmentationを行うことができる．

###実装
```python:data_augment.py
import numpy as np 
import glob
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array, load_img, array_to_img, ImageDataGenerator

#ディレクトリ内の画像を読み込み
files = glob.glob("読み込むディレクトリ" + "/*.PNG")

for i,file in enumerate(files):
    #画像をPIL形式で読み込み
    img = load_img(file,target_size=(2436,1125))
    #PIL形式をnumpyのndarray形式に変換
    x = img_to_array(img)
    #ImageDataGeneratorクラスがndarray形式の4次元配列を要求するため
    x = x.reshape((1,) + x.shape)

    #クラス生成
    datagen = ImageDataGenerator(
        rotation_range=25,#画像の回転
        fill_mode='constant',#境界周りの埋め方の指定
        width_shift_range=0.2,#水平シフト
        height_shift_range=0.2,#垂直シフト
        horizontal_flip=True,#水平方向にランダムに反転
        vertical_flip=True)#垂直方向にランダムに反転

    #画像を生成して保存
    aug_img = datagen.flow(x, batch_size = 1, save_to_dir = "生成した画像を保存するディレクトリ", save_prefix = "umi", save_format = "jpg")

    #作成する画像の数だけループ
    for i in range(10):
        batch = aug_img.next()
```

###生成結果
　上記のソースの処理の結果以下に示す「生成画像の例」のような画像が生成できた

![スクリーンショット 2019-03-04 22.01.34.png](https://qiita-image-store.s3.amazonaws.com/0/323592/d6ec315e-7ca9-b27a-ea5c-385df72f42a7.png)

![スクリーンショット 2019-03-04 22.41.40.png](https://qiita-image-store.s3.amazonaws.com/0/323592/80b70ae4-ca70-c570-9fe7-7f82ac12023c.png)


- 生成後の画像の枚数
     - 高坂穂乃果:483枚
     - 南ことり:349枚
     - 園田海未:598枚

#まとめ
　今回はスクフェスのカードからスクショにより学習データを作成しDataAugmentationを行った．
次回は~~(気力があれば)~~今回作成したデータを使いニューラルネットワークでの学習を行いたい．

#参考
[画像の前処理-Keras Documentation](https://keras.io/ja/preprocessing/image/)
GitHub入門

# やること
GitHubとは何か？を説明。
# 目標
Gitとどのように連携させるか？がわかること。
# GitHubとは？
## 一言でいうと
Gitを用いたソフトウェア開発プロジェクトのための共用ウェブサービス
## GitHubを利用する３つのメリット
複数人でコードを「共有」し開発を進めるための便利機能が充実。
* フォーク：誰かのレポジトリをコピーし、（オリジナルの編集アクセス権は無いものの）分派を作り改変すること。
* プルリクエスト：自分の行った変更をオリジナルに反映させるため、オリジナルのオーナーに「通知」を送ること。
* マージ：（プルリクエストされた）人のコードを自分のコードに導入すること。
# 現在の自分の連携状況
あやふやなところは？がついています。ざっくり言うと
* Google Colab: ML系開発。Google Driveに元データ保存。→GHへ直接Push
* Local: それ以外、あるいは軽いML系開発。→GitでLocalへコミット。GHへPush
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253276/45921875-3f3f-6885-8334-aeb755ff1700.png)
BitmapSource派生クラスの使い方

#概要
ざっくりBitmapSource派生クラスの使い方。

## BitmapImageクラス

ファイルなどから画像を引っ張ってくるときに使う。

``` cs
private void Button_Click_1(object sender, RoutedEventArgs e)
{
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.FilterIndex = 1;
    openFileDialog.Filter = "Jpeg ファイル(.jpg)|*.jpg|All Files (*.*)|*.*";
    bool? result = openFileDialog.ShowDialog();

    if (result != false)
    {
        tb_FileName.Text = openFileDialog.FileName;
        var uri = new Uri(tb_FileName.Text, UriKind.Absolute);
        var image = new BitmapImage(uri);
        MyImage.Source = image;
    }
}
``` 

## RenderTargetBitmapクラス
UI部品(FlameworkElement)を画像として取り込むときに使う

``` cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    SaveFileDialog saveFileDialog = new SaveFileDialog();
    saveFileDialog.FilterIndex = 1;
    saveFileDialog.Filter = "Jpeg ファイル(.jpg)|*.jpg|All Files (*.*)|*.*";
    bool? result = saveFileDialog.ShowDialog();

    if (result == true)
    {
        var canvas = new RenderTargetBitmap((int)MyCanvas.Width, (int)MyCanvas.Height, 96, 96, PixelFormats.Pbgra32);
        canvas.Render(MyCanvas);

        var jpg = new JpegBitmapEncoder();
        jpg.Frames.Add(BitmapFrame.Create(canvas));
        using (Stream stm = File.Create(saveFileDialog.FileName))
        {
            jpg.Save(stm);
        }
    }
}
```

## TransformedBitmapクラス

各種Transform派生クラスと組み合わせて、回転、拡大等するときに使う

``` cs
private void Button_Click_2(object sender, RoutedEventArgs e)
{
    SaveFileDialog saveFileDialog = new SaveFileDialog();
    saveFileDialog.FilterIndex = 1;
    saveFileDialog.Filter = "Jpeg ファイル(.jpg)|*.jpg|All Files (*.*)|*.*";
    bool? result = saveFileDialog.ShowDialog();

    if (result == true)
    {
        // 画像を取ってきて
        var canvas = new RenderTargetBitmap((int)MyCanvas.Width, (int)MyCanvas.Height, 96, 96, PixelFormats.Pbgra32);
        canvas.Render(MyCanvas);

        // 1/2にタテヨコ縮小して
        var sct = new ScaleTransform(0.5, 0.5);
        var canvas2 = new TransformedBitmap(canvas, sct);

        // 90度回転して
        var rtt = new RotateTransform(90);
        var canvas3 = new TransformedBitmap(canvas2, rtt);

        // 保存する
        var jpg = new JpegBitmapEncoder();
        jpg.Frames.Add(BitmapFrame.Create(canvas3));
        using (Stream stm = File.Create(saveFileDialog.FileName))
        {
            jpg.Save(stm);
        }
    }
}
```

## コード

https://github.com/tera1707/WPF-/tree/master/015_BitmapSource_Series
Ubuntu 18.04 LTS > Monitor > スリープから解除時にモニタの横幅が半分になる > 対処:ドライバインストール

```txt:動作環境
Ubuntu 18.04 LTS
GeForce GTX 1070
EIZO EV2750-BKR (2560 x 1440)
EIZO EV2750-BKR (2560 x 1440)
```

## 症状

- モニタ二台
    - DVI接続を一台
    - HDMI接続を一台
- スリープから復帰後、DVI接続のモニタが横幅半分の画面サイズになる（下記参照）

![IMG_0279.JPG](https://qiita-image-store.s3.amazonaws.com/0/32870/55ff7cf9-7ba7-81f7-1a34-634af19afef2.jpeg)


## 対応

参考
- [Ubuntu18.04にNvidia Driver, CUDA, cuDNNを入れる](https://qiita.com/nakamura21/items/2b2ff6524710d167d618)

情報感謝です。

```
$ sudo ubuntu-drivers autoinstall
```

上記を実施後、再起動しました。
スリープ状態にしてから復帰後、モニタは正常に表示されるようになりました。
【vim】気長にvimrcを育てていくページ

マウスまで手をのばすのが面倒くさい、なるべくホームポジションからも手を動かしたくない・・・
そんな横着なプログラマーに最適なエディターはやっぱりvimですよね！！
すべてをvimで完結させたい、いくいくはvimをIDEとして活用したい、そんな私が、徒然と思い立つままにvim環境を育てていくページです。
#最新
```~/.vimrc
"エディタ内での文字コード
set encoding=utf-8
"ファイル読み込み時のエンコーディング
set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8
"検索時のハイライト表示
set hls
"タブ入力を複数の空白入力に置き換える
set expandtab
"画面上でタブ文字が占める幅
set tabstop=2
"改行時に前の行のインデントを継続する
set autoindent
"行番号表示
set number
"自動インデントでずれる幅
set shiftwidth=2
"連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅
set softtabstop=2
"インサートモードからノーマルモードへの切り替えをESCから変更
inoremap <silent> jj <ESC>
"キーバインドを変更
nnoremap s <Nop>
nnoremap sj <C-w>j
nnoremap sk <C-w>k
nnoremap sl <C-w>l
nnoremap sh <C-w>h
nnoremap sJ <C-w>J
nnoremap sK <C-w>K
nnoremap sL <C-w>L
nnoremap sH <C-w>H
nnoremap sn gt
nnoremap sp gT
nnoremap sr <C-w>r
nnoremap s= <C-w>=
nnoremap sw <C-w>w
nnoremap so <C-w>_<C-w>|
nnoremap sO <C-w>=
nnoremap sN :<C-u>bn<CR>
nnoremap sP :<C-u>bp<CR>
nnoremap st :<C-u>tabnew<CR>
nnoremap sT :<C-u>Unite tab<CR>
nnoremap ss :<C-u>sp<CR>
nnoremap sv :<C-u>vs<CR>
nnoremap sq :<C-u>q<CR>
nnoremap sQ :<C-u>bd<CR>
nnoremap sb :<C-u>Unite buffer_tab -buffer-name=file<CR>
nnoremap sB :<C-u>Unite buffer -buffer-name=file<CR>
```
# 2020/10/11
キーバインドの変更。

```~/.vimrc
nnoremap s <Nop>
nnoremap sj <C-w>j
nnoremap sk <C-w>k
nnoremap sl <C-w>l
nnoremap sh <C-w>h
nnoremap sJ <C-w>J
nnoremap sK <C-w>K
nnoremap sL <C-w>L
nnoremap sH <C-w>H
nnoremap sn gt
nnoremap sp gT
nnoremap sr <C-w>r
nnoremap s= <C-w>=
nnoremap sw <C-w>w
nnoremap so <C-w>_<C-w>|
nnoremap sO <C-w>=
nnoremap sN :<C-u>bn<CR>
nnoremap sP :<C-u>bp<CR>
nnoremap st :<C-u>tabnew<CR>
nnoremap sT :<C-u>Unite tab<CR>
nnoremap ss :<C-u>sp<CR>
nnoremap sv :<C-u>vs<CR>
nnoremap sq :<C-u>q<CR>
nnoremap sQ :<C-u>bd<CR>
nnoremap sb :<C-u>Unite buffer_tab -buffer-name=file<CR>
nnoremap sB :<C-u>Unite buffer -buffer-name=file<CR>
```

# 2020/04/11
```~/.vimrc
"インサートモードからノーマルモードへの切り替えをESCから変更
inoremap <silent> jj <ESC>
```

# 2019/03/04
## はじめてのvimrc
さしあたり簡易の初期設定。

```~/.vimrc
"エディタ内での文字コード
set encoding=utf-8
"ファイル読み込み時のエンコーディング
set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8
"検索時のハイライト表示
set hls
"タブ入力を複数の空白入力に置き換える
set expandtab
"画面上でタブ文字が占める幅
set tabstop=2
"改行時に前の行のインデントを継続する
set autoindent
"行番号表示
set number
"自動インデントでずれる幅
set shiftwidth=2
"連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅
set softtabstop=2
```
Mac OS MojaveでMySQL5.7の組み合わせで mysqlのgemのビルドエラー

Mac OS Mojave+MySQL5.7の環境で、mysqlのgemがビルドエラーになってしまう。

```
bundle install
ake "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
result.c:326:40: warning: incompatible pointer types assigning to 'my_bool *' (aka 'char *') from 'bool *' [-Wincompatible-pointer-types]
    wrapper->result_buffers[i].is_null = &wrapper->is_null[i];
                                       ^ ~~~~~~~~~~~~~~~~~~~~
result.c:328:40: warning: incompatible pointer types assigning to 'my_bool *' (aka 'char *') from 'bool *' [-Wincompatible-pointer-types]
    wrapper->result_buffers[i].error   = &wrapper->error[i];
                                       ^ ~~~~~~~~~~~~~~~~~~
2 warnings generated.
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2
```

```
ld: library not found for -lssl
```
と出ているので、opensslのリンクができない模様。

opensslを入れて、パスを指定した所、無事ビルドが通ることを確認。

```
brew install openssl
gem install mysql2 -v '0.4.10' --source 'https://rubygems.org/' -- --with-cflags=\"-I/usr/local/opt/openssl/include\" --with-ldflags=\"-L/usr/local/opt/openssl/lib\"

Building native extensions with: '--with-cflags="-I/usr/local/opt/openssl/include" --with-ldflags="-L/usr/local/opt/openssl/lib"'
This could take a while...
Successfully installed mysql2-0.4.10
Parsing documentation for mysql2-0.4.10
Installing ri documentation for mysql2-0.4.10
Done installing documentation for mysql2 after 0 seconds
1 gem installed
```

High Sierraの時は大丈夫だったので、環境依存の模様。
こういう時に、dockerのありがたみを実感する。
TensorFlow Hubを使ってみた

[TensorFlow Hub](https://www.tensorflow.org/hub)の[画像分類チュートリアル](https://www.tensorflow.org/hub/tutorials/image_retraining)をやってみたので、インストールから実行までを書いておきます。特に詰まることなく2時間ほどで終わりました。以前、[転移学習をやったときにある程度苦労した](https://qiita.com/FukuharaYohei/items/fcad2d74f2b753191548)ので、少し拍子抜けするくらい簡単でした(チュートリアルだからですが・・・)。
**[TensorFlow Hub](https://tfhub.dev/)を使えば他人の作ったモデルを使って転移学習ができます**。訓練に時間とリソースを使う機械学習・深層学習の世界では非常にありがたいです！少なくても最低限のことを理解しなくてはと思い、チュートリアルをしました。

# 環境
前提としてCURLとpyenvが入っているくらいでしょうか。pyenvインストールと設定については記事[「UbuntuにpyenvとvenvでPython開発環境構築」](https://qiita.com/FukuharaYohei/items/2820f7bda6678ce26ea7)を参照ください。

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|pyenv|1.2.9|複数Python環境を使うことがあるのでpyenv使っています|

#手順
## 1. Python系環境準備
### 1.1. Python3.6インストール

TensorFlowがpython3.7で動かないという情報が多数あり、確認すると[公式ガイド](https://www.tensorflow.org/install/pip#1.-install-the-python-development-environment-on-your-system)に下記の記載があるのでPython3.6をpyenv使ってインストール。

> Requires Python 3.4, 3.5, or 3.6"

```bash
$ pyenv install 3.6.8
```

Pytho3.6をpyenvのグローバルに設定して確認。

```bash
$ pyenv global 3.6.8
$ python --version
Python 3.6.8
```

### 1.2. venv環境設定
py36という名前でvenv仮想環境作成し、有効化。

```bash
cd <directory>
python -m venv py36
source py36/bin/activate
```

pipを最新化。

```bash
pip install --upgrade pip
```

## 2. TensorFlow Hubインストール
### 2.1. TensorFlowとTensorFlow Hubインストール
[公式ガイド](https://www.tensorflow.org/hub/installation)に従ってTensorFlowとTensorFlow Hubをインストールして確認。TensorFlow1.13.1とTensorFlow Hub0.2.0がインストールされました。

```bash
pip install "tensorflow>=1.7.0"
pip install tensorflow-hub
pip freeze
```

## 3. 画像分類チュートリアル実行
独自のフォルダ作らずに[画像分類チュートリアル](https://www.tensorflow.org/hub/tutorials/image_retraining)どおりにやりました。

### 3.1. 画像ダウンロード
花画像をダウンロードして解凍します。

```bash
cd ~
curl -LO http://download.tensorflow.org/example_images/flower_photos.tgz
tar xzf flower_photos.tgz
```

※後で調べたのですが、自分のデータセットを使いたい場合は、フォルダごとに単一種類の画像があればいいようです。また、使用する[プログラム](https://github.com/tensorflow/hub/blob/master/examples/image_retraining/retrain.py)内で画像サイズを調整してくれているので、画像サイズ事前調整は不要です。

### 3.2. 訓練プログラムダウンロード
Pythonの訓練プログラムをダウンロードします。

```bash
mkdir ~/example_code
cd ~/example_code
curl -LO https://github.com/tensorflow/hub/raw/master/examples/image_retraining/retrain.py
```

### 3.3. 訓練実行
Pythonプログラムを実行して、終わるまでだいたい30分くらいかかりました。このプログラムの中でTensorFlow Hubから訓練モデルをダウンロードして転移学習しています。

```bash
python retrain.py --image_dir ~/flower_photos
```

### 3.4. 実行結果の確認
TensorBoardを起動して実行結果を確認します。

```bash
tensorboard --logdir /tmp/retrain_logs
```

ブラウザでターミナルに表示された下記のURLを開きます。
http://ubuntu:6006/

最初からaccuracyとクロスエントロピーの値がそこそこいい感じなのは、転移学習ならではですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/a952a85d-3567-9cf8-82d3-0872e9347e14.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/a839ea83-5f1f-0b48-d882-639e4d85b291.png)

「Confusion Matrix(混合行列)があればいいのに」と思ったのですが、[Tutorialのプログラムを複雑にしたくないという理由で実装していない](https://github.com/tensorflow/hub/issues/182)ようです。
[このスレッド](https://stackoverflow.com/questions/53102664/calculating-f1-score-precision-recall-in-tfhub-retraining-script/53182833)を参考に実装できるのかもしれません。
AndroidStudioにおけるadb.exe多重起動時の対処方法

adb.exeが多重起動している場合、Android実機（ **HTC U11** ）での動作確認ができない。

![0201.png](https://qiita-image-store.s3.amazonaws.com/0/242897/ef41a919-efa5-493e-941b-6bfec675334b.png)


#### 対処法
サービスの「HTCMonitorService」を停止する。
![0202.png](https://qiita-image-store.s3.amazonaws.com/0/242897/cb31aea8-0fcd-e3e3-2238-cdfe1244c0bd.png)


以下コマンドを実行し、adb.exeを全て消す。（タスクマネージャーからkillしてもOK）

```
adb kill-server
```

その後に実機を接続し、以下コマンドを実行

```
adb devices
```

実行結果
![0203.png](https://qiita-image-store.s3.amazonaws.com/0/242897/cb9b85a0-f36b-67be-2331-012eba5a0b89.png)
【作業効率UP】Railsでブラウザの更新を自動化する方法

Railsでファイルを更新した時に、ブラウザもリロードしなければいけないのですが、更新ボタンを押し続けるのは面倒なこともあります。
ホットリロードを実現するgemを導入して自動化してしまいましょう。
## 【作業効率UP】Railsでブラウザの更新を自動化する方法
https://github.com/guard/guard-livereload/wiki/Usage
このサイトの内容を実行すればOKです。

まずはgemを追加

```ruby:Gemfile
group :development, :test do
  gem 'guard-livereload', '~> 2.5', require: false
end

```

インストール・初期化

```bash
$ bundle
$ guard init livereload
```

次に、必要なChrome拡張をブラウザに追加します。
https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei//go

次は、ターミナルを開き

```bash
$ guard
```
を実行。

そして、もう一つターミナルを開き


```bash
$ rails s
```
これで完了です。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
python columnsの抽出・削除・名前の変更について

# 初めに
pandas.DataFrameでcolumnsの抽出・削除・名前の変更方法についてまとめてみた。

# 目次
**1.抽出**
 a.基本的な抽出(df['a'], df.loc, df.iloc 等)
 b.複数のカラムをまとめて抽出
 c.カラム名に特定の文字を含むカラムのみを抽出

**2.削除**

**3.名前の変更**
 a.基本的な変更(カラムを指定して変更、全て変更）
 b.全てのカラム名に文字を追加する


今回使用するdataは以下の通り
以下、dataが変更される時があるが、常にこのデータにリセットして使用しているものとする。

```python
import pandas as pd
df = pd.DataFrame({'a':[1,11],
                  'b':[2,22],
                  'c':[3,33],
                  'ab':[4,44]},
                 index=['one','two'])
```

||a|b|c|ab|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|


##1.抽出
#####a.基本的な抽出(df['a'], df.loc, df.iloc 等)
・カラム名で抽出

```python
df['a']

# one     1
# two    11
# Name: a, dtype: int64
```
```python
df.a

# one     1
# two    11
# Name: a, dtype: int64
```
```python
df.loc[:,'a']

# one     1
# two    11
# Name: a, dtype: int64
```
・カラムの番号で抽出

```python
df.iloc[:,0]

# one     1
# two    11
# Name: a, dtype: int64
```
#####b.複数のカラムをまとめて抽出

```python

df[['a','b']]
```

||a|b|
|---|---|---|
|one|1|2|
|two|11|22|

```python

df.loc[:,'a':'b']
```

||a|b|
|---|---|---|
|one|1|2|
|two|11|22|

```python

df.iloc[:,0:3]
```

||a|b|c|
|---|---|---|---|
|one|1|2|3|
|two|11|22|33|

#####c.カラム名に特定の文字を含むカラムのみを抽出(aをカラム名に含むカラムのみ抽出)

```python
columns_name = df.columns
selected_col = [col for col in columns_name if 'a' in col]
df[selected_col]
```

||a|ab|
|---|---|---|
|one|1|4|
|two|11|44|

##2.削除
・元データに変更を加えないとき

```python
df.drop('a', axis=1)
```
||b|c|ab|
|---|---|---|---|
|one|2|3|4|
|two|22|33|44|

・元データを変更する時、inplace=Trueを加える

```python
df.drop('a', axis=1, inplace=True)
```
||b|c|ab|
|---|---|---|---|
|one|2|3|4|
|two|22|33|44|

・まとめて削除する時

```python
df.drop(['a','b'], axis=1, inplace=True)
```
||c|ab|
|---|---|---|
|one|3|4|
|two|33|44|

##3.名前の変更
#####a.基本的な変更
・元のデータに変更を加えないとき

```python
df.rename(columns={'a':'A'})
```
||A|b|c|ab|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|


・元のデータに変更を加えるときは、inplace=Trueを加える。

```python
df.rename(columns={'a':'A'}, inplace=True)
df
```
||A|b|c|ab|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|

・複数のカラム名もまとめて変更できる

```python
df.rename(columns={'a':'A'
                   'b':'B'}, inplace=True)
df
```
||A|B|c|ab|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|

・全てのカラムを変更する場合(元データも変更される)
※データのカラム数と新たに指定するカラム名の数は同じでなければいけない

```python
df.columns = ['A','B','C','AB']
```
||A|B|C|AB|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|

#####b.全てのカラム名に文字を追加する

```python
df_name = 'new_' + df.columns
df.columns = df_name
df
```
||new_a|new_b|new_c|new_ab|
|---|---|---|---|---|
|one|1|2|3|4|
|two|11|22|33|44|


以上です。
間違いや追加した方がいい内容があればご教授ください。
カスタムURLスキーム起動

# カスタムURLスキームの勉強で参考になったサイトのまとめ

## 超初心者向け
[[Android]Deeplink(Custom URL Scheme)を使ってアプリからアプリを起動する](http://yotiky.hatenablog.com/entry/2018/05/21/_%5BAndroid%5DDeeplink%28Custom_URL_Scheme%29%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%A2%E3%83%97%E3%83%AA%E3%81%8B%E3%82%89%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B)
PWA: Workbox Core 和訳

#Workbox Core
参照元ページ: https://developers.google.com/web/tools/workbox/modules/workbox-core

##Workbox Coreとは?

(すべてのファイルや機能が入った)単一のファイルをダウンロードせすに、ディベロッパーが必要なモジュールファイルのみを選んで使用できることを目的にWorkboxは作られました。

しかしながらモジュール間に重複した部分があります。例えば、各モジュールはコンソールを操ったり、意味のあるエラーやネットワーク、キャッシュを利用します。それぞれのモジュールが行なっている共通のロジックの実装を避けるために、`workbox-core`はコードの共有化を行なっています。

`workbox-core`はディベロッパーに機能を提供しますが、(ログやキャッシュのみではなく)ディベロッパーのためというよりむしろ各々のモジュールに対して内部で利用できるロジックを提供しています。

# デフォルトのキャッシュの名前を確認し変更する

Workboxは`workbox.core.cacheNames`経由でキャッシュを定義します。

```js

console.log(workbox.core.cacheNames.precache);

console.log(workbox.core.cacheNames.runtime);

console.log(workbox.core.cacheNames.googleAnalytics);
```

これらのキャッシュ名は`prefix(接頭辞)`、`名前`、`suffix(接尾辞)`のパーツで組み立てられます。名前はキャッシュの利用に基づいて変わります。

```
<prefix>-<cache id (precache | runtime | googleAnalytics)>-<suffix>
```

デフォルトの命名規則は`setCacheNameDetails()`に渡す値で変更可能です。

```js

workbox.core.setCacheNameDetails({
  prefix: 'my-app',
  suffix: 'v1',
  precache: 'install-time',
  runtime: 'run-time',
  googleAnalytics: 'ga'
});

// Will print 'my-app-install-time-v1'
console.log(workbox.core.cacheName.precache)

// Will print 'my-app-run-time-v1'
console.log(workbox.core.cacheName.runtime)

// Will print 'my-app-ga-v1'
console.log(workbox.core.cacheName.googleAnalytics)
```

もしあなたがWorkboxを複数のプロジェクトで使っており、それぞれのプロジェクトが同じlocalhostを使用している場合、prefixとsuffixを使用することでプロジェクト間のキャッシュのコンフリクトを回避することができます。

# Skip Waiting and Clients Claim
新しいサービスワーカーを配信して、即座にウェブページをそのサービスワーカーのコントロール下におきたい場合があります。（それはデフォルトの[サービスワーカーのライフサイクル](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle)をスキップすることになります）

下記のように書くことで`workbox-core`が、ライフサイクルを簡単にスキップさせてくれます。

```js

workbox.core.skipWaiting();
workbox.core.clientsClaim();
```
【Xcode】自作埋め込みCocoa Touch Frameworkを実機インストール＆Archiveする

# 問題
親プロジェクトに対して埋め込みの`Cocoa Touch Framework`を実機デバックしようとすると

```swift
dyld: Library not loaded: @rpath/freamwork.framework/freamwork
  Referenced from: /var/containers/Bundle/Application/4CD9C96B-257C-4A75-B2C5-581490DB904B/freamwork_sample.app/freamwork_sample
  Reason: image not found
```
という実行時エラーが起きてアプリがクラッシュする。
この問題はシミュレータでは起きない。

# 解決方法
`親project -> General -> Embedded Binries` に、`子project.framework` を追加する。
<img width="901" alt="スクリーンショット 2019-03-04 21.23.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/268579/d53e7872-fb0c-f12f-5f16-b6b781c4ba3d.png">
↑＋ボタンを押す。

<img width="895" alt="スクリーンショット 2019-03-04 21.23.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/268579/ade03a03-cda6-d7a3-d57c-95aa5b4a4925.png">
↑今回の例では`freamwork.freamwork`を選択して親プロジェクトの`Embedded Binries`に追加する。


# 引っかかりどころ
`親project -> Build Phases -> Link Binary With Libraries` に`子project.framework`を追加すればOKかと思ってた

<img width="903" alt="スクリーンショット 2019-03-04 21.47.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/268579/cc5cb60d-dfd4-5bf8-d218-59c8c2e01fc9.png">
多分`.freamwork`ファイルを直接`Add To File`するだけなら、ここに追加するだけで大丈夫なはず。
今回のように`.xcodeproj`ファイルごと埋め込みライブラリとしてビルドする場合には、実機＆Archiveでは上記の対応が必要になるっぽい。

# そもそも埋め込みライブラリを作る方法
`Cocoa Touch Framework`を作りたい場合に、完全に別プロジェクトとしてビルドして、生成して`.freamwork`ファイルを毎回親プロジェクトにコピーしてもいいですけど、できれば同じプロジェクトのように作業したい。
ブレークポイントとかで止まってくれるように。

そういう場合には、あらかじめ作成しておいた`Cocoa Touch Framework`を親プロジェクトに`Add File To`するだけで、簡単に同じワークススペースで作業できるようになる。


<img width="969" alt="スクリーンショット 2019-03-04 21.59.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/268579/21d1d04a-9ecc-ef00-1ea0-8c1c44a05e42.png">
↑今回の例では`freamwork.xcodeproj`をAddする。
ちなみに、`Copy item into ...`はチェックつけない方が良いとおもう。（プロジェクトファイルが複製されると、意図していない変更などややこしくなりそう）


# あとがき
最近の情報がなかなか情報が見つからず（2014くらいの情報しかない。というかシミュレータと実機両方でビルドできるターゲットを作ろう！みたいな記事しかない)、丸二日解決に時間を要しました・・・
自作フレームワークを作っている同じ悩みを抱えている人の助けになれば
サーバー基礎メモ

##サーバーとは
サービス・機能を提供するコンピュータのこと。
サービス・機能を受ける側のコンピュータはクライアント側という。

普段私たちがwebを見るときはサーバー側から情報を送付してもらい
ブラウザ（クライアント側）で受け取った内容を表示している。

![FireShot Capture 13 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/4cef58dc-63ec-010f-d5d4-3e9bf5983e3d.png)

##サーバーの仮想化って？？
1台の物理的なサーバーの中に、仮想的に複数のサーバーを構築します。
１台の物理サーバーなのに複数のサーバーのように見えることがサーバの仮想化です。

![FireShot Capture 14 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/e3a67846-5b45-a6ce-49f2-17f8273df2b0.png)


各サーバーのリソースを余らせることなく使用できるので効率の良いリソース管理が行える。

##レンタルサーバーの種類
###１、共有サーバー
複数ユーザーで１台のサーバーを使用する。
![FireShot Capture 15 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/52cf6825-1774-2674-876f-88d2529de3de.png)


###２、専用サーバー
１人のユーザーで１台のサーバーを使用する。
ユーザーが必要に応じてOSやアプリケーションを選んで構築出来る。
![FireShot Capture 16 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/38bd4328-9181-42f1-ed93-0ddf02128713.png)


###３、VPSサーバー
バーチャルプライベートサーバー(virtual private server)のこと。
1台のサーバーの中に、仮想的に複数のサーバーを構築しているサーバー。
ユーザーが必要に応じてOSやアプリケーションを選んで構築出来る。
専用サーバーとの違いは一台のサーバーを使用しているわけではなく、
サーバーを共有している。また、回線も共有しているので、専用サーバーと比較すれば
性能は低めだが、安価に自由度の高いサーバーを構築することが出来る。
![FireShot Capture 17 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/b407aad7-39b9-b9a5-fb88-5f2714f4d685.png)


###４、クラウドサーバー
クラウドとはインターネットを通して利用できるサービス。
物理サーバーは存在しており、複数のサーバー群をまとめて１つの仮想サーバーを構築する。
専用サーバーなど他のレンタルサーバーだと容量を増やしたい場合にサーバーをもう１台用意する必要があるが、
クラウドサーバーでは容量を簡単に増やせるなど拡張性が高く、スペックの変更もオンライン上で簡単に行える。

必要なときに必要な分のスペックを簡単に用意することがクラウドサーバーの強み。

![FireShot Capture 18 - 無題のプレゼンテーション - Google スライド_ - https___docs.google.com_presentati.png](https://qiita-image-store.s3.amazonaws.com/0/272935/a4265f4f-1235-e5c6-694b-cccb916279d8.png)
IT系の資格試験を調べてみた

# 概要

IT系の資格を取ろうと思って人気の資格を調べてみた。

# 調べ方
## ITスキル標準(ITSS)

ITSSキャリアフレームワークと認定試験・資格の関係(ISV Map Ver11r2)
http://www.ssug.jp/qualification/

## Global knowledge

15 Top-Paying IT Certifications for 2019
https://www.globalknowledge.com/us-en/resources/resource-library/articles/top-paying-certifications/

## 日経xTECH

人気沸騰のIT資格、取得したい資格ランキング
https://tech.nikkeibp.co.jp/atcl/nxt/column/18/00465/101100003/

## 試験センター

- プロメトリック http://www.prometric-jp.com/
- ピアソンVUE https://www.pearsonvue.co.jp/

# 取ろうと思った資格
## UML

UMLの資格は2つある。OMG謹製のOCUPと日本独自のUMTP。以下の考察からUMTPがよさそう。

- OCUPの特長
    - 試験問題はUMLの言語仕様重視（らしい）。
    - OMGのOCUPは2015年にOCUP2に移行したが、OCUP2に対応した参考書がほぼない。（2019年3月時点）
    - 世界的にUMLの資格そのものがあんまり注目されてないが、しいてあげるならOCUP。
- UMTPの特長
    - 日本国内では、日本独自のUMTPが優勢。
    - UMTPは実務重視。言語仕様より「どうやって設計するか？」に主眼を置く。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google トレンドで「UMTP, OCUP - すべての国、過去 12 か月間」の 人気度の動向 を見る - <a href="https://t.co/cgfTmcw4fR">https://t.co/cgfTmcw4fR</a></p>&mdash; kannkyo (@kannkyoshi) <a href="https://twitter.com/kannkyoshi/status/1097244448050696192?ref_src=twsrc%5Etfw">2019年2月17日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google トレンドで「UMTP, OCUP - すべての国、過去 12 か月間」の 地域で比較した内訳 を見る - <a href="https://t.co/ML6yDAQSoy">https://t.co/ML6yDAQSoy</a></p>&mdash; kannkyo (@kannkyoshi) <a href="https://twitter.com/kannkyoshi/status/1097244473241755648?ref_src=twsrc%5Etfw">2019年2月17日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## Linux

Linuxの資格は2つある。以下の考察からLPICがよさそう。

- CompTIA Linux+
    - 世界的にはCompTIA Linux+が注目されている。
    - CompTIA Linux+に合格すると、パートナーシップによりLPIC-1も取得できる。
- LPIC
    - 日本ではLPICだけが日本語対応なので、LPICが注目されている。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google トレンドで「LPIC, CompTIA - すべての国、過去 12 か月間」の 人気度の動向 を見る - <a href="https://t.co/eU3cLwlYyV">https://t.co/eU3cLwlYyV</a></p>&mdash; kannkyo (@kannkyoshi) <a href="https://twitter.com/kannkyoshi/status/1097240753191800832?ref_src=twsrc%5Etfw">2019年2月17日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google トレンドで「LPIC, CompTIA - すべての国、過去 12 か月間」の 地域で比較した内訳 を見る - <a href="https://t.co/Ffsqo4LZ1r">https://t.co/Ffsqo4LZ1r</a></p>&mdash; kannkyo (@kannkyoshi) <a href="https://twitter.com/kannkyoshi/status/1097240781771878400?ref_src=twsrc%5Etfw">2019年2月17日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## ITサービスマネジメント

ITILしかない。が、現在以下の2つがあるので要注意。

- ITIL 4 ファウンデーション
    - [シラバス](https://www.axelos.com/getmedia/9abec3eb-c4e0-4b61-90ca-10bab8f87faa/ITIL-4-candidate-syllabus.aspx)
- ITIL ファウンデーション (ITIL V3とかITIL 2011とも）
    - [シラバス](https://www.axelos.com/getmedia/b2d6281d-14aa-45fc-abb7-4d228810c328/The_ITIL_Foundation_Certificate_Syllabus_v5-5.aspx)

2019年2月からITIL 4に順次移行中で、日本語版はまだITILしかない。
CS193p class note - 1 introduction

##### What's in iOS:

Cocoa Touch: Map kit, Web view, Image picker...
Media: Audio, video playback, core animation...
Core Services: Threading, file access, URL utilities...
Core OS

#####Shortcut keys:
Control + Command + Space -> show emoji
type "color literal" -> show "color" in Xcode
Control + Drag from storyboard -> create a IBAction or IBOutlet
#####Memo:
- All instance variable (properties) need to be initialized
- Swift is a type-inference language. It means it will if it can infer the type for you. 
- Property observer: every time the property changes, didSet will be called.
- Optional is a type. And it has only two states (set and not set). Optional is just like a enum in Swift. When it is in "set" state, we access the associated value; when it is in "not set" state, it's simply a nil.
gitでリポジトリのホットなファイルを見つける

##経緯

既存のプロジェクトにジョインしたときに、色々なファイルが多くてパンクしていました。そこでどのファイルが盛んに変更されているのかを注目して、そのホットなファイルがそのプロジェクトで肝となっていると思い、まずはそのコミット数が多いファイルを特定してどのような流れになっているのか調べてみようと思いました。
githubでは、コミット数ごとにファイルを検索できたりしないので今回はよく修正されているホットなファイルの見つけ方を共有しておきます。


##方法
今回知りたいプロジェクトで下記のコマンドを叩いてあげます。

```git
git ls-files | while read file ; do   commits=`git log --oneline -- $file | wc -l`;   echo "$commits - $file"; done | sort -n
```

###結果
コミット数順にターミナルに表示することができました。

```
※省略
       2 - Pods/RxSwift/RxSwift/SwiftSupport/SwiftSupport.swift
       3 - Podfile
       3 - Podfile.lock
       3 - Pods/Manifest.lock
       3 - Pods/Pods.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/Pods-conpass.xcscheme
       3 - Pods/Pods.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/Pods-conpassTests.xcscheme
       3 - Pods/Pods.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/Pods-conpassUITests.xcscheme
       3 - Pods/Pods.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/RxCocoa.xcscheme
       3 - Pods/Pods.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/RxSwift.xcscheme
       3 - conpass.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcschemes/xcschememanagement.plist
       4 - Pods/Pods.xcodeproj/project.pbxproj
       6 - conpass/AppDelegate.swift
       7 - conpass.xcodeproj/xcuserdata/shiroma_daisuke.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
       7 - conpass.xcworkspace/xcuserdata/shiroma_daisuke.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
      11 - conpass/ConnpassModel.swift
      12 - conpass/ConnpassViewModel.swift
      13 - conpass.xcodeproj/project.pbxproj
      37 - conpass/ViewController.swift
```
Vimにemmet-vim導入

htmlスニペットがきくvimプラグインを入れた。
とりあえずメモ程度に。

### ドキュメント

https://github.com/mattn/emmet-vim

https://emmet.io/

### 設定追加

vimrcに以下の一行を追加しました。

```
NeoBundle 'mattn/emmet-vim'
```

### 読み込み

```
:NeoBundleInstall
```

### 使い方

`div>a.hoge` と打ち、`<C-y>,`と打つと以下のように展開。

```
<div><a class="hoge" href=""></a></div>
```

そのほかはドキュメントを参照。
JScript(サクラエディタマクロ)でSetが使いたい

# 環境
サクラエディタ   Ver. 2.2.0.1
Windows 10

# マクロ

仕事上、サクラエディタのマクロに頼ることが多い。
サクラエディタはオールドスタイルなエディタではあるが、その中では比較的高機能だと思う。

マクロはWSHのJScriptで記述できるのだが、本流のJavaScriptではないので、最近のECMAScriptの新しい構文が軒並み使えない。

ただ、サクラエディタのマクロでは

* 画像を出す
* エディタのメニュー自体を拡張

みたいなところまではできないため、そこまで高機能な構文は要らない気もしている。

…のだが、非常に痒い点が1点。

**Setが使えない。**

Setがあると、重複行や仲間外れをどうこうする感じのマクロが非常に書きやすい。

ところで、JavaScriptにはSetによく似たものとしてオブジェクト(連想配列)がある。
そこで、キーの部分をSetとして使えば良いと考えて、Setもどきを実装してみた。

機能は限定的。中身に使える値は文字列のみ。
JSON.stringify的な何かがあれば、文字列以外も使えそうだが…(JScriptなので無い)

```javascript:Setもどき&重複行削除マクロ


var pseudoSet = function( str ){
  var hash = {}

  this.add = function( str ){
    hash[ str ] = true;
  }

  this.has = function( str ){
    if( true === hash[ str ] ) {
      return true;
    }
    else {
      return false;
    }
  }

  this._delete = function( str ){
    delete hash[ str ];
  }

}


// ここからエディタマクロ
var text = GetSelectedString(0);
lines = text.split("\n");

var set = new pseudoSet();
var deleted_duplicate = [];
for( var i = 0; i < lines.length; ++i ){
  var str = lines[i];
  if( !set.has( str ) ) deleted_duplicate.push( str );
  set.add( str );
}

var outText = deleted_duplicate.join("\n");
Editor.InsText( outText );

```

「ツール」→「名前を指定してマクロを実行」か、「共通設定」→「マクロ」タブから登録することで実行できる。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/28988/68fd6623-6f22-6c27-bc09-05c8bf502332.png)


選択行を入力とするので、入力後、カーソル選択。

```:入力
a
b
c
c
c

```

すると、以下のように出力される。
重複除去という目的は達成できた。


```:出力
a
b
c

```


集合演算(intersectionみたいなの)は別途実装すること。

前に空行区切りの2つの文字列群の積集合と差集合を取るマクロを書いたことがあったので、
良い形に直して追記したい(書けたら追記するが、未定)。

# サクラエディタのヘルプ

* GitHub移行後のHelp(v2.x以降): [サクラエディタ ヘルプ目次](https://sakura-editor.github.io/help/)
* SourceForge時代のHelp(v1.x): [サクラエディタ ヘルプ目次](http://sakura-editor.sourceforge.net/htmlhelp/)
CentOS6でSCLのPython2.7をvirtualenv配下で使う

## はじめに
Python2.6はすでにサポートされなくなってしまいpip等でインストールしても動作しないのが増えてきてしまっています。
しかし悲しいことにCentOS6ではPython2.6のサポートなのでいろいろと困ってしまいます。

SCL(Software Collections)にPython2.7はいるのですが、sclを起動後、virtualenvで使おうとするとエラーが出て失敗してしまいます。

```
$ python --version
python: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory
```
で、もう少し使いやすくしよう。というので試行錯誤(?)したのが今回の方法です。

## ざっくりな説明
1. scl上でvirtualenv環境を作成する
2. 上記で作成した仮想環境配下のbin/activateを/opt/rh/python27/enableファイルの中身を参考にして書き換える
3. scl環境から抜ける
4. virtualenv環境でPython2.7が使える！

## そこそこな説明
### sclをインストールしてsclのpython27をインストールする
  この方法はあちこちあるので省略[^1]
### scl配下でvirtualenvを実行する
```
$ scl enable python27 "virtualenv py27"
```
とか
### 作成したvirtualenv配下のactivateを書き換える
書き換える箇所としてはPATHの書き換えているあたりの下にLD_LIBRARY_PATHとMANPATHとPKG_CONFIG_PATHを設定し、deactivate関数の中で書き換えた環境変数をもとに戻す感じ。
書き換える環境変数の内容は/opt/rh/python27/enableの中身を参照。

diffをとると以下みたいになると思う

```diff
--- py26/bin/activate
+++ py27/bin/activate
@@ -29,6 +29,21 @@
         unset _OLD_VIRTUAL_PS1
     fi

+    if [ -n "$_OLD_LD_LIBRARY_PATH" ] ; then
+        export LD_LIBRARY_PATH="$_OLD_LD_LIBRARY_PATH""
+        unset _OLD_LD_LIBRARY_PATH"
+    fi
+
+    if [ -n "$_OLD_MANPATH" ] ; then
+        export MANPATH="$_OLD_MANPATH"
+        unset _OLD_MANPATH
+    fi
+
+    if [ -n "$_OLD_PKG_CONFIG_PATH" ] ; then
+        export PKG_CONFIG_PATH="$_OLD_PKG_CONFIG_PATH"
+        unset _OLD_PKG_CONFIG_PATH
+    fi
+
     unset VIRTUAL_ENV
     if [ ! "$1" = "nondestructive" ] ; then
     # Self destruct!
@@ -46,6 +61,15 @@
 PATH="$VIRTUAL_ENV/bin:$PATH"
 export PATH

+_OLD_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH=/opt/rh/python27/root/usr/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
+
+_OLD_MANPATH="$MANPATH"
+export MANPATH=/opt/rh/python27/root/usr/share/man:${MANPATH}
+
+_OLD_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+export PKG_CONFIG_PATH=/opt/rh/python27/root/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
+
 # unset PYTHONHOME if set
 # this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
 # could use `if (set -u; : $PYTHONHOME) ;` in bash
```
### 実行
後はいつもと同じようにvirtualenv配下のフォルダに入ってsource bin/activateするだけでpython 2.7が動く!

## おわりに
python2.7も2020年には終了しちゃうんですよね。

[^1]: centos-release-sclとcentos-release-scl-rhの違いはなんだろう？
Raspberry Pi でパスワードのリセット

Raspberry Pi でよくパスワードがわからなくなる。というか、正しいはずなのに、なぜかアクセスできなくなる（SSH）

そういうときのad Hocな対処を書いておく

症状としては、

 - SSH経由でログインできない
 - raspberry piを直接操作する分にはログインパスワードはいらないので操作できる

という感じです。そもそも直接raspberry pi の操作ができないという場合にはこの方法は使えません。自分は普段は、モニターもキーボードも何も繋げない状態でraspberry pi を稼働させていて、いつもssh経由で操作しています。

なんか、数週間ラズパイにログインせずにほっておくと勝手にパスワード変わる気がするんだよな（そんなことはあるのか？）

で、対処法

 - raspberry piにモニタ・キーボード・マウスをつないで直接操作する
 - コマンドプロンプトで下記のようにする

```command
sudo passwd pi
```

passwd コマンドを sudo で実行するのがポイント。
３つ目のpiはパスワードを変更したいユーザー名なので、変更したいユーザー名が違う場合はそこを適宜変える。

このコマンドを実行すると、古いパスワードを聞かれることなしに、新しいパスワードを何にするか聞かれるので、新しいパスワードをあらかじめ考えておいて、それを打ち込む。
打ち込むと、確認のために再度パスワードを聞かれるので、同じ文字列を再び打つ。

こうすることで、パスワードは変更（更新）されて、sshでそのパスワードを使ってログインできるようになった。

いや、でも、sudoするときにパスワード聞かれないけど、これ大丈夫なのだろうか
PowerPointでアプリアイコンを作る

# はじめに
表題の通り、PowerPointでアプリアイコンをつくる話です。
PowerPointは本来プレゼン用ツールですが図形描画系のツールも充実しており、簡単なアイコンなどであればパッと作れちゃいます。

# 要件
- 512 x 512 サイズのアイコンをつくる
- png形式で保存
- 透過処理も可能
- PowerPointで製作する


# 事前に必要なもの
- PowerPoint（本記事では Office 365 の バージョン 1812 を使用）
- PowerPointの操作知識


# 手順 
1.PowerPointを開き、「新規＞新しいプレゼンテーション」を開く
![1.png](https://qiita-image-store.s3.amazonaws.com/0/68832/d62fa320-9937-631c-3751-03a1e61f955f.png)

2.プレゼンテーション上にある、デフォルトのオブジェクトをすべて削除する。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/68832/c5b84084-e49a-7f34-f781-da0e3be62441.png)

3.メニューの「デザイン＞ユーザー設定＞スライドのサイズ＞ユーザー設定のスライドサイズ」から以下の設定をし、OKをクリック

- 幅：8.678 cm 
- 高さ：8.678 cm 

※このサイズが丁度 512pxサイズのアイコンが作れるスライドサイズになります。
　環境に応じて変わる可能性があるので、そのあたりは微調整してください。
※OKをクリックするとコンテンツサイズを同行するか聞かれますが
　「最大化」でも「サイズに合わせて」でもどちらでも大丈夫です
![3.png](https://qiita-image-store.s3.amazonaws.com/0/68832/d1c6ac55-b8ae-29f0-2d28-e8c1903931fa.png)

4.スライドサイズが正方形になります。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/68832/6971ff00-e624-aa0a-ab8b-cab923dd9ac3.png)

5.メニューの「挿入＞図＞図形＞正方形」を選択し設置。
　設置したオブジェクトをスライドにピッタリ収まるようにリサイズする。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/68832/1720e28b-ab5a-3634-a306-02dfaec94bca.png)


6.設置したオブジェクトを選択した状態でメニューの「書式＞図形のスタイル」から以下のように設定。
　アイコンの土台が完成します。

- 図形の塗りつぶし：塗りつぶしなし
- 図形の枠線：枠線なし

![6.png](https://qiita-image-store.s3.amazonaws.com/0/68832/2cc40a23-87ed-bc2e-79c0-b0c98ff07f81.png)

7.PowerPointの機能でアイコンを作ります。以下サンプル。（単純すぎてすみません…）
![7.png](https://qiita-image-store.s3.amazonaws.com/0/68832/9b5d9aaa-b498-390d-c605-7f6ea0c96096.png)

8.「6」と「7」でつくったオブジェクトをすべてを選択状態にし、右クリックから「グループ化＞グループ化」を選択。
　選択状態にしたオブジェクトが１つグループとしてまとまった状態になります。
![8.png](https://qiita-image-store.s3.amazonaws.com/0/68832/3721feca-f1f6-fd5e-b56b-f777414e543d.png)

9.グループ化されたオブジェクトを右クリックし「図として保存」を選択。
　保存先を聞かれるので任意の場所に保存をしてください。

以上でアイコンの製作が完了します。


# まとめ
サンプルは図形だけでつくりましたが、PowerPointには図形の他にアイコン、３Dモデル、SmartArtなどの描画ツール、ワードアートやグラデーションなどいろいろな機能があります。
これらをうまく組み合わせることでオリジナリティのあるアイコンを制作することができるかと思います。
RSpecでの一時的な非同期Jobのqueue_adapter設定変更メモ

# 結論
あるspecファイルだけで一時的に `queue_adapter` を変更したい場合は

```ruby
require 'spec_helper'

RSpec.describe HogeJob do
  include ActiveJob::TestHelper
  Rails.application.config.active_job.queue_adapter = :test # <= これ

  it do
    perform_enqueued_jobs do
      HogeJob.new.perform("my")
    end
  end
end
```
のように設定すること。

# 悪い例
次のように設定してはいけない。他のspecまで影響を受けてしまい、 `:test` アダプター以外を使う前提でテストが書かれている場合にテストが通らなくなってしまった。

```ruby
require 'spec_helper'

RSpec.describe HogeJob do
  include ActiveJob::TestHelper
  ActiveJob::Base.queue_adapter = :test # <= ダメ

  it do
    perform_enqueued_jobs do
      HogeJob.new.perform("my")
    end
  end
end
```

# 理由
誰か教えて

# ちなみに
すべてのspecに `queue_adapter` の変更を反映したい場合は普通 `config/environments/test.rb` で設定するよね。
今回は一部のspecでのみ、変更したくなって上記のハマりポイントを踏んだ。