OmniAICreator/Qiita-1.07M huggingface dataset:
amazon athenaでhash値を使ったtrain/test splitをした話

# 3行で
・amazon athenaにクエリを投げて、hash値を使ったtrain/test splitをしたい
・amazon athenaのhash関数は戻り値がbinaryで、binaryを扱える関数が貧弱すぎてかなりハマった
・文字列には`TO_UTF8`関数、`XXHASH64`関数、`FROM_BIG_ENDIAN_64`関数を順次適用するとhash値が得られる。

# モチベーション
データのリークを避けつつtrain/testにデータを分けるのに有効な方法として、hash値を使うものがある。
すべてのレコードをランダムで分けるだけでは、train/testにリークが発生する可能性がある。
（例えば、小売店の取引履歴があったとして、同じIDの人が何度か取引したデータが別のレコードとして扱われていれば、それらがtrain/test間のリークを起こす）
hash値は引数に対して一意的な値を与えられる（と仮定していい）ので、train/testにまたがってほしくないデータは同じhash値になるように同じ値をhash関数に渡す。
そのhash値をもとに分割すればいい。（例えばhash値のmodをとるなどして）
当然アプリケーション側のコードでも実現できることだが、DB側でもできるようにしたかった。
（データが大きくなったときに有利になったりしないかな・・・）

# 内容
### 結論
ナイーブなやり方ではうまく行かないし、うまく行かないやり方を紹介しようと思うが、結論の前にあまりごちゃごちゃと書くのも読みにくいのでまずはうまくいくコードを紹介する。

```sql:query
SELECT FROM_BIG_ENDIAN_64(XXHASH64(CAST('Amazon Redshift' AS varbinary))) AS hash
```

結果は以下

| hash | 
|:-----------|
| -5401464031556620364      | 

例えば、これでtrain/test splitをやるなら、

```sql:query
SELECT 
  Your_feature
  FROM_BIG_ENDIAN_64(XXHASH64(CAST(<your_key>))) AS hash
FROM
  Yourdatabase.Yourtable
WHERE
  MOD(ABS(FROM_BIG_ENDIAN_64(XXHASH64(CAST(<your_key>)))),10) < 8
```
などとやれば、`<your_key>`のカラムから重複を除いておよそ80%のレコードが得られます。

### うまく行かないやり方その1　CAST AS INTEGER
僕も最初に試したやつですが、hash関数の戻り値を`CAST AS INTEGER`で型変換して数値にする方法です。
例えば以下のクエリはエラーです

```sql:query
SELECT CAST(MD5(CAST('Amazon Redshift' AS varbinary)) AS INTEGER)
```
>Cannot cast varbinary to integer

と言われてしまいます。

これは、下記のドキュメントで言及されています。
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/functions-operators-reference-section.html

>Amazon Athena クエリエンジンは、Presto 0.172 に基づいています。これらの関数の詳細については、Presto 0.172 の関数と演算子を参照してください。
https://prestodb.github.io/docs/0.172/index.html

そしてバイナリに使える関数は以下です
https://prestodb.github.io/docs/0.172/functions/binary.html
なんであれ、ここのリストにない操作で実現しようと思わないほうが無難でしょう。


### うまく行かないやり方その2　MD5をSUBSTRで短くする
よく使われるhash関数である`MD5`ですが、戻り値が124ビットです。
バイナリを数値に戻す関数は`FROM_BIG_ENDIAN_64`ですが、124ビットのバイナリを引数にとれません。
どうせそんなに桁数なんていらないんだから、途中の桁で打ち切ってしまえ、私はそう考えました。
__驚くべきことに、Presto 0.172では`SUBSTR`はサポートされていません__
実際、以下のクエリはエラーです

```sql:query
SELECT SUBSTR(MD5(CAST('Amazon Redshift' AS varbinary)),8)
```

>Unexpected parameters (varbinary, integer) for function substr. Expected: substr(varchar(x), bigint, bigint) , substr(varchar(x), bigint) , substr(char(x), bigint) , substr(char(x), bigint, bigint)

というエラーを吐きます。
Presto 0.225ではサポートされているようで、そっちの情報ばっかり出てきたのでめちゃくちゃ混乱しました・・・。


### もう一度結論
https://prestodb.github.io/docs/0.172/functions/binary.html
というわけで、上記リストにある関数からhash値取得と数値に変換ができる組み合わせを選ぶと
hash関数: `XXHASH64`
変換: `FROM_BIG_ENDIAN_64`
ということになるわけです。

# 教訓
困ったら公式ドキュメントを・・・
ラズパイでとりあえずタッチ機能を実装するまで

#目的
ラズパイを買ってきて、とりあえず画面タッチと画面キーボードを使えるようにするところまで

#パッケージリストを最新版にアップデート
```
sudo apt-get update
sudo apt-get upgrade
```

#日本語環境のインストール
```
sudo apt-get install uim uim-anthy
```

終わったら、設定から言語やロケーションを日本にして再起動する

#画面タッチ機能のインストール
```
sudo apt-get install xinput-calibrator
```

#画面タッチ機能を開く
```
xinput_calibrator
```

この座標をメモしておく
170 3959 170 3948

#画面のコンフィグの設定
画面コンフィグ設定ファイルを開く

```
sudo nano /etc/X11/xorg.conf.d/99-calibration.conf
```

座標の設定を変更

```
Section "InputClass"
        Identifier      "calibration"
        MatchProduct    "ADS7846 Touchscreen"
        Option  "Calibration"   "ここを上書き"
        Option  "SwapAxes"      "1"
EndSection
```

#タッチキーボードのインストール
```
sudo apt-get install matchbox-keyboard
sudo apt-get install ttf-kochi-gothic xfonts-intl-japanese xfonts-intl-japanese-big xfonts-kaname
```

これでアクセサリ→キーボードでタッチキーボードを出すことができる

#画面の上下変更
画面の向きが気に入らなかったので、上下を変更した

ブート設定のファイルを開く

```
sudo nano /boot/config.txt
```

ディスプレイの向き変更

```
lcd_rotate=2
```

ブート設定を変更したので、再起動して設定反映

ちなみにdisplay_rocate=2の設定ではディスプレイは上下反対になるが、タッチキーには反映がされてないようで、タッチした場所がおかしくなってしまったため、こちらのコマンドで行なった


最近のラズパイはメモリ４GB可能みたいだし、下手な中古PC買うくらいならこっちでいいのでは...？
visualforceでのページ送りを作ってみた

#結果画面の次へ前へボタン

よくある次のページへとか前へや一番最初、一番最後とかあると思いますが、
実際に作ってみました。

##完成イメージ
<img width="542" alt="スクリーンショット 2019-09-17 20.32.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/088f8bd0-63d7-ef89-f067-b02d14233314.png">

検索画面を押すと。。

<img width="1059" alt="スクリーンショット 2019-09-17 20.32.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/681ec60c-8014-95a3-c628-91266d6b0986.png">

左上に前へ次へボタンが出てきて

<img width="251" alt="スクリーンショット 2019-09-17 20.32.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/91b7d830-2782-ff1c-73d3-992128eaf5ae.png">

前へいけない時は押せないみたいな表示になるって感じですね。

##ソース

```ruby:sample.vfp
<apex:pageBlock title="商品一覧" >
 <apex:outputtext value="全件 : {!resultList.size} 件 " />
   <apex:commandButton value="前へ" action="{!previous}" disabled="{!firstRecord == 0}"/>
   <apex:commandButton value="次へ" action="{!next}" disabled="{!firstRecord + 10 > resultList.size}"/>
   <apex:commandButton value="再検索" action="{!research}"/>
     <table class="branch-table">
        <thead>
           <tr>
             <th>編集</th><th>商品ID</th><th>商品名</th><th>商品ファミリ</th><th>商品コード</th>
           </tr>
        </thead>
        <tbody>
           <apex:repeat value="{!resultList}" var="result" first="{!firstRecord}" rows="10">
             <tr>
               <td class="tabledata"><apex:outputLink value="https://salesforce.com/{!result.Id}/e?" target="_blank">編集</apex:outputLink></td>
               <td class="tabledata"><apex:outputText value="{!result.Id}"/></td>
               <td class="tabledata"><apex:outputText value="{!result.Name}"/></td>
               <td class="tabledata"><apex:outputText value="{!result.Family}"/></td>
               <td class="tabledata"><apex:outputText value="{!result.Productcode}"/></td>
             </tr>
           </apex:repeat>
        </tbody>
      </table>
</apex:pageBlock>
```

左上のボタン部分はこのような感じで実装しました。
それぞれが次へ前へのメソッドを呼び出すって感じです。

次にApex

```ruby:sample.apex
public class SamplePageForStudyController {
  public Integer firstRecord {get;set;}
  public static Integer ROWSRECORD = 10;

  public sample(){
      this.firstRecord = 0;
  }
  public void previous(){
      this.firstRecord -= ROWSRECORD;
  }
  public void next(){
      this.firstRecord += ROWSRECORD;
  }
}
```

今回使っている方法はapex:repeatのいいところを活かした実装の形です。
firstにIntegerを入れることでListに入っている値の最初に表示するレコードを決めることができます。

それを利用して、それぞれのメソッドでROWSRECORDをfirstRecordに加算、減算していくという実装です。
またdisabledでfirstRecordが0ということは1ページ目なので前へボタンは使えない。
さらにfirstRecordに10加えた数値が結果のリストサイズよりも大きければ次に表示するモノはないので使えないようにしています。

##オマケ

再検索ボタンを押した際には再度検索画面を表示する実装をしているのですがこの際にfirstRecordを0にすることを忘れないようにしておきましょう。

```ruby:sample.apex
    public void research(){
        this.conditions = new Product2();
        this.doSearchFlag = false;
        this.firstRecord = 0;
    }
```

じゃないと再検索した際になぜか2ページ目から表示されるようになってしまいます笑

もっと違った実装もありますのでまた小出しにしていきます！
カスタムUIFontが適用されない

## 状況
カスタムフォントを使いたい

とりあえず、
1. プロジェクトにフォントファイル(.otf, .ttf)を挿入
2. 挿入したフォントのプロジェクトターゲットを指定
3. プロジェクトのbundleにフォントが入っているか確認
4. `Info.plist`に新しいrowを追加

と、[手順として一般的な方法](https://codewithchris.com/common-mistakes-with-adding-custom-fonts-to-your-ios-app/)を実行したがカスタムフォントが適用できない..

## 結論（というかよくあるであろうミス）
#### 正しい`Info.plist`に書く！

`Info.plist`のパスを確認してみてください。
`Info.plist`は同じ名前でテスト用の別ファイルが存在したりするので要注意です

僕はここでドハマリしたので共有させていただきます..

## 参考サイト
https://stackoverflow.com/questions/30554758/cannot-add-custom-font-to-xcode
https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app
https://codewithchris.com/common-mistakes-with-adding-custom-fonts-to-your-ios-app/
S3のurlを使ったファイルの操作がわからない

# ファイルのURLはある
URLはある。
アクセスすればファイルは参照出来る。

ただ、そのURLの使い方がよくわからない。
こんな感じでblobに変換するでいいのだろうか。

```sample.js
axios({
  url: awsのpublic/配下のURL,
  method: 'GET',
  responseType: 'blob'
})
  .then(
    response => {
      // 疑似ダウンロードリンク作成
      let mimeType = 'application/pdf'
      // 変換
      let blobData = new Blob([response.data], { type: mimeType })
      const url = URL.createObjectURL(blobData)

      // ファイルダウンロードさせたり
    })
  .catch(
    err => {
      console.log(err)
    }
  )
```
dashで位置パラメタを退避しようとしたら入れ子の配列が使えるようになった

配列代わりに何かと便利な位置パラメタを退避できると嬉しいときがあるような気がした。
(esc関数の定義は[ここ](https://qiita.com/opiliones/items/d8c9299e0b7c4e5830c5)を参照)

```bash
arr() {
  local RET args= arg

  for arg in "$@"; do
    esc "$arg"
    printf ' %s' "$RET"
  done
}
alias backup_args='arr "$@"'
alias restore_args='eval "set --"'
```

```
$ set -- 'a b' "c'"
$ hoge="`backup_args`"
$ echo $hoge
'a b' 'c'\'''
$ set --
$ echo "$1"

$ restore_args "$hoge"
$ echo "$1"
a b
$ echo "$2"
c'
```

evalで解釈するとシングルクォート囲みの文字列が各フィールドにsetされるように
文字列を作成するだけなのだが、これを使うと任意の文字列の配列が入れ子で
作成できることに気がついた。

```
$ m=$(arr "`arr 1 2 3`" \
          "`arr 4 5 6`" \
          "`arr 7 8 9`")
$ echo $m
' '\''1'\'' '\''2'\'' '\''3'\''' ' '\''4'\'' '\''5'\'' '\''6'\''' ' '\''7'\'' '\''8'\'' '\''9'\'''
$ restore_args "$m"
$ echo $2
'4' '5' '6'
$ restore_args "$2"
$ echo $1
4
$ echo $2
5
```

位置パラメタを汚さずにアクセスできるようにiter関数を定義してみる。

```bash
iter() {
  local head=$1 tail=$2
  eval "restore_args \"\$$2\""
  [ $# -gt 0 ] || return
  eval "$head='$1'"
  shift
  eval "$tail="'"`backup_args`"'
}
```

```
$ a="`arr 1 2 3 4`"
$ while iter i a; do echo $i; done
1
2
3
4
```

※性能を気にする人はコマンド置換を避けて定義し直すとよいかも。
ファイルから対話型 Bash Shell の標準入力に入力する

# ファイルから対話型 Bash Shell の標準入力に入力する
対話型の Bash Shell ツールをテストしたときの覚書です。
従来、対話型Shellのテストはいちいち手入力して出力を確認していましたが、ファイルからの標準入力に置換えられることがわかった、というお話です。

## 背景：Bash Shell ツールのテストの難しさ
普段、Bash Shell のツールを使うことがちょくちょくありますが、テストはお粗末になりがちでした。
中でも、**対話型の Shell ツールに関しては、都度手入力し、出力確認をしていたことで、テストの網羅度が非常に低くなっていました。**

## Shell ツール（例）

単純に入力を求めて、入力されたものを表示するだけのShellです。

```bash:実行例
$ bash sample_tool.bash
整数を入力してください >
1
1が入力されました

$ bash sample_tool.bash
整数を入力してください >
1.1
整数以外が入力されました:1.1
```

<details><summary>コード</summary><div>

```bash:Code
#!/bin/bash

if [ $# -gt 0 ]; then
        echo "引数は必要ありません"
        exit 1
fi

echo "整数を入力してください >"
read INPUT

expr $INPUT + 1 > /dev/null 2>&1
INPUT_CHECKER=$?

if [ $INPUT_CHECKER -gt 1 ]; then
        echo 整数以外が入力されました:${INPUT}
        exit 1
fi

echo ${INPUT}が入力されました

```

</div></details>


## テスト内容（例）

|#| 入力 | 期待値 | 説明 |
|:-----:| :-------- | :----| :----|
|正常系1| 1 | 1が入力されました | 実行モードで1を入力する|
|正常系2| 100 | 100が入力されました | 実行モードで100を入力する|
|異常系1| a | 整数以外が入力されました | 実行モードでaを入力する|
|異常系2| 1.1 | 整数以外が入力されました | 実行モードで1.1を入力する|

## 何が問題か

* インタラクティブでのテストを前提としているため、テストの自動化などができない
* 毎回入力して、アウトプットを確認するなどの手間がひどい


# 対話型のShellのテスト方法
**標準入力を置き換える**という方法で、いちいち対話入力して確認する必要がなくなりました。
具体的な方法は以下の通り。

## Linux では標準入力は置き換えられる
`[command] < [textファイル]`で、textファイルの内容で標準入力を置き換えられます。
これによって、入力を自動化し、自動テストなどに利用できることがわかりました。

## 実際の例

こんな感じの入力用ファイルを用意しておきます。

```bash:input.txt
1
```

後は上記の通り、これを入力に置き換えるだけ。

```bash:標準入力の置き換え
$ bash sample_tool.bash < input.txt
整数を入力してください >
1が入力されました
```

確かに期待したとおり、標準入力が置き換わっています。

## 複数回の対話を行う場合
入力用のファイルを複数行にすると、複数回の対話に対応可能です。

### ツール（例）
複数回の入力を求めて、それをそれぞれ出力させるだけのものです。

```bash:実行例（対話）
$ bash sample_tool.bash
整数1を入力してください >
3
3が入力されました

整数2を入力してください >
u
整数以外が入力されました:u
```


<details><summary>コード</summary><div>

```bash:Code
#!/bin/bash

main(){
        if [ $# -gt 0 ]; then
                echo "引数は必要ありません"
                exit 1
        fi

        echo "整数1を入力してください >"
        read INPUT_1
        numberChecker $INPUT_1

        echo ${INPUT_1}が入力されました
        echo ""

        echo "整数2を入力してください >"
        read INPUT_2                                                                                                 
        numberChecker $INPUT_2

        echo ${INPUT_2}が入力されました
        echo ""
}

numberChecker () {
        expr $1 + 1 > /dev/null 2>&1
        INPUT_CHECKER=$?                                                                                             
        if [ $INPUT_CHECKER -gt 1 ]; then
                echo 整数以外が入力されました:$1
                exit 1
        fi
}

main                      
```

</div></details>

### 入力置き換え（例）

入力用のファイルを用意しておきます。複数回の入力の対応のために、複数行に分けます。

```bash:input.txt
1
2
```

置き換えを行うと、たしかに入力が複数回行われていることがわかりました。


```bash:実行例（入力置き換え）
$ bash sample_tool.bash < input.txt
整数1を入力してください >
1が入力されました

整数2を入力してください >
2が入力されました
```

## 更にこれを活かすには～テスト用Shellの作成～

テスト用のShellを書いたりしたのですが、それはまた別の機会に。
.bashrcファイルとは？

# 目的

- .bashrcファイルを編集するとき、そもそも当該ファイルがなんなのかわかっていないので明確にする。

# .bashrcとは

- 設定ファイルの一つ。
bashで使う際に必要な設定が書かれている。
- bashを起動した時に読み込まれるもの、bashを起動する都度実行される。
bashで使う設定のみを記載する。起動時に読んでほしいものは記載しない。
- ただログインしただけじゃ読み込まれない。
デフォルトの設定だとログイン時には.bashrcは実行されないが、ログイン時に実行するようにもなる。
- `bash`と入力してEnterを押下した時に実行されるファイルのこと。

# そもそもbashって？

- shellの一つ
- 人からの入力をPCに伝えるプログラム。
- bashにもいくつかの種類のshellが存在する。
Azure IoT のソリューション構築に役立つサイト


#Azure で IoT を構築する時に見ておきたい情報
IoTのソリューション構築において、そこそこ有用な資料なのですが、あまり存在が知られていないようなので紹介します。

##Azure の開発者ガイド
この **第5章 が「IoTでビジネスをつなげる」**という内容になっていて、Azure の IoT 向けサービスにどのようなモノがあり、どんな場面で使えるかがシンプルに記載されています。

日本語版もあるので是非。

こんなやつ。
<img width="758" alt="DevGuide.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/eda55055-66fe-146b-403a-370edc8f4177.png">


[英語版] The Developer’s Guide to Azure (2019年5月版)
https://azure.microsoft.com/en-us/campaigns/developer-guide/
→ PDFでダウンロードできます (Azure_Developer_Guide_eBook.pdf)

[日本語版] Azure の開発者ガイド (2019年5月版)
https://azure.microsoft.com/ja-jp/campaigns/developer-guide/
→ PDFでダウンロードできます (Azure_Developer_Guide_eBook_ja-JP.pdf)


##Azure リファレンスアーキテクチャ(PDF)
こちらは開発者ガイドより詳しい内容で、がっつり書かれています。
<img width="721" alt="RefAch.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/d821f701-0377-6501-56a8-b193a5855187.png">


[Azure IoT 参照アーキテクチャ](https://docs.microsoft.com/ja-jp/azure/architecture/reference-architectures/iot/) で説明されている **リファレンスアーキテクチャ** のもっと詳しいものがPDFで入手できます。
※2019年9月時点: バージョンは若干古いですが日本語翻訳版も出てます。

[英語版] Ver2.1
Microsoft Azure IoT Reference Architecture (Ver2.1 英語) 9/26/2018
http://download.microsoft.com/download/A/4/D/A4DAD253-BC21-41D3-B9D9-87D2AE6F0719/Microsoft_Azure_IoT_Reference_Architecture.pdf

[日本語版] Ver2.0 日本語 (2018年8月翻訳版)
http://download.microsoft.com/download/6/1/6/6166d6c1-0ac3-4869-840d-53bcc85319db/Microsoft_Azure_IoT_Reference_Architecture_J_V2.0.pdf

---
ちなみに、この辺りの資料は定期的にアップデートされているのですが、下記URLのようにマイクロソフト社のブログで**「新しいバージョン出したよ！」**って感じで、たまに情報発信されていますので、今後新しいバージョンが欲しい方はチェックしてみてください。
[Azure IoT Reference Architecture update (Microsoft Blog - Udapte)](https://azure.microsoft.com/en-us/blog/azure-iot-reference-architecture-update/)
vbsの作法 その33

#概要

vbsの作法調べてみた。
マウスを動かしてみた。

#サンプルコード


```
Dim sh
Set sh = CreateObject("WScript.Shell")
sh.Run "%windir%\System32\rundll32.exe MouseControll.dll,_SetMouseXY@16 100,100"


```


以上。
Vue.js で SSR の props を boolean で渡す際に json_encode が便利かも

# Vue.js で SSR の props を boolean で渡す際に json_encode が便利かも

というか サーバサイドから渡す際には基本的に JSON 形式で (json_encode の結果として) 渡したほうがよいかもという話になります。

## サーバサイドレンダリングからの props 指定の方法

Laravel のドキュメントに記載されているように [サーバサイドレンダリングからの出力を
Vue.js での props に渡すような方法](https://laravel.com/docs/5.8/blade) は広く知られていることでしょう。

> The @json directive is also useful for seeding Vue components or data-* attributes:
> 
> ```html
> <example-component :some-prop='@json($array)'></example-component>
> ```

[slot 経由などという余計な手段をとる必要などはあんまりありません。](https://qiita.com/ysKuga/items/3bb48e62b45a547b5a36)

## Boolean 単品を props として渡したい

前述の事例では配列を JSON 化して props に渡していました。
では Boolean などはどのようにしたらよいでしょう？

答えは・・・

```html
<example-component :some-bool='@json($bool)'></example-component>
```

`$array` の代わりに `$bool` を渡しました。
`$bool` は PHP の出力において Boolean 型を想定するものです。

これは正しいのでしょうか？
以下の記述にて試してみると

```php:test.php
var_dump(
	json_encode(true),
	json_encode(false)
);
```

```bash
$ php test.php
string(4) "true"
string(5) "false"
```

出力としては `true`, `false` それぞれの文字列としての出力が行われました。
これがサーバサイドからのレンダリングであれば JavaScript の `true`, `false` に合致します。
処理の結果としては正しく見えますが・・・

## JSON の RFC について

上記の事例が PHP の出力として間違っていないかを確認するためにマニュアルを見てみると
[PHP:json_encode - Manual](https://www.php.net/manual/ja/function.json-encode.php) では

> 注意:
> 
> PHP の実装は、 » [RFC 7159](http://www.faqs.org/rfcs/rfc7159.html) の JSON のスーパーセットです

そして RFC 7159 の `3.  Values` にて

>    A JSON value MUST be an object, array, number, or string, or one of the following three literal names:
> 
>       false null true

> JSON の値は `オブジェクト`, `配列`, `数値`, `文字列` あるいは以下三つのうちのいずれか
> `false`, `null`, `true`

と記載されているようです。

これは PHP の `json_encode()` の引数として指定可能であるのは上記の事例の型であり
`true`, `false` が文字列化するのは JSON としての Boolean として適切な記述に変換されている・・・と思われます。

PHP 単に Boolean を出力すると空白などになってしまうようですからね・・・
任意のディレクトリ群の中のファイル数を数え上げるシェルスクリプト

普段シェルスクリプトを書かないのでメモっておく
"d"で始まって"1"か"2"で終わる全てのディレクトリの中にある全てのファイルを数え上げる

```bash
n_files=0
for dir_name in `ls | grep ^d | grep [12]$`
do
  n_files=$((n_files += `ls -1 $dir_name | wc -l`))
done
echo $n_files
```
Azure のスキルアップに役立つサイト (Microsoft Learn - IoT編)

#自分のペースで勉強できる Microsoft Learn
みなさん [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/?WT.mc_id=AZ-MVP-4040034) は活用していますか？
ここには、好きな時に自分のペースで、オンライン上で学べるコンテンツが揃っています。

今回は IoT シナリオを想定して、初心者にお勧めコンテンツ(日本語化されたもの)を紹介します。

##Microsoft Learn で提供されている IoT 系のお勧めコンテンツ
- [機械学習、Azure IoT Hub、Azure Stream Analytics を使用してリアルタイムで画像を分析する](https://docs.microsoft.com/ja-jp/learn/modules/build-ml-model-with-azure-stream-analytics/?WT.mc_id=AZ-MVP-4040034)

 - 結構ボリュームのあるコンテンツですが、
 **IoT Hub -> Stream Analytics -> Functions -> SQL Database -> Power BI** までの一連の構成を学ぶ事ができ、しかも、Azure の AI関連のサービス **Cognitive Services の Custom Vision** も利用した、ちょっと面白い内容になっています。

<img width="459" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/e15d2945-bcde-3514-f773-ab2476e49c6d.png">
---
- [Azure Stream Analytics を使用したデータ ストリームの処理](https://docs.microsoft.com/ja-jp/learn/modules/introduction-to-data-streaming/?WT.mc_id=AZ-MVP-4040034)

 - 読むだけなので、サクッと終わりますが、**Stream Analytics の基礎の基礎**が分かり易くまとめられています。

<img width="457" alt="002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/31923ea9-533e-083a-da08-94dc9e77e266.png">
---
- [Azure Stream Analytics を使用してデータを変換する](https://docs.microsoft.com/ja-jp/learn/modules/transform-data-with-azure-stream-analytics/?WT.mc_id=AZ-MVP-4040034)
 - **Stream Analytics の入出力の設定やクエリの書き方**など、最低限必要な基礎知識はここで学ぶことができます。

<img width="456" alt="003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/6a9a93dc-734d-e73c-35f5-28e682221a25.png">
---
- [Azure IoT Central でコーヒー販売機を監視管理する](https://docs.microsoft.com/ja-jp/learn/modules/monitor-and-manage-device-with-iot-central/?WT.mc_id=AZ-MVP-4040034)
 - 仮想的な「コーヒーマシン」をIoT Centralに接続し、水温が異常値を示した時にアラートメールを送る、といった感じで、**IoT Central を使用する上での基礎をシナリオベースで学ぶ**ことができます。
 
<img width="457" alt="004.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/74db1e11-9e89-83bc-64f1-1e08ce8e7293.png">
Goでbase64を画像でS3へアップロードする

### はじめに

意外にbase64をバッファに書き込んでアップロードする記事がなかったので書く!
急いでる人は一番下にコード載せてるんでそれで！

### 前提
- フロントからjson等でstringで画像を変換したbase64が送られてくる事
- 拡張子も一緒に送られる事
- `go get -u github.com/kelseyhightower/envconfig`

### kelseyhightower/envconfig

[kelseyhightower/envconfig](https://github.com/kelseyhightower/envconfig)
このパッケージで環境変数を扱いやすくする。

```go

type Env struct {
    S3AK string
    S3SK string
}
```

この様に構造体を定義しておくと

```go

var env Env
envconfig.Process("", &env)
env.S3AK // = 環境変数に設定したS3AK
env.S3SK // = 環境変数に設定したS3SK
```

で、環境変数に設定してある `S3AK` (アクセスキー)と `S3SK` (シークレットキー)が取得できます。
詳しくはgithubを確認して下さい。(もちろんS3AKとかじゃなくて名前はなんでも大丈夫です！)


### base64をバッファに書き込む

フロントから送られてきたbase64をまずはバッファに書き込んであげましょう！
ここのS3Serviceは定義しなくても大丈夫です。

引数はimageBase64はあれで, fileExtensionには拡張子が入ってるとします。

```go

func(s3 S3Service) UploadS3(imageBase64 string, fileExtension string) error {
    data, _ = base64.StdEncoding.DecodeString(imageBase64)
    wb := new(bytes.Buffer)
    wb.Write(data)    
}
```

これだけでもう準備できました！（エラーは握り潰してます。。w）

次はS3のCredentialとUploaderの作成です！

### S3

先ほど説明したenvconfigを使いましょう！

```go

func(s3 S3Service) UploadS3(imageBase64 string, fileExtension string) error {
    var env Env
    _ = envconfig.Process("", &env)

    sess := session.Must(session.NewSession(&aws.Config{
        Credentials: credentials.NewStaticCredentials(env.S3AK, env.S3SK, ""),
        Region: aws.String("ap-northeast-1")
    }))

    uploader := s3manager.NewUploader(sess)
    
}
```
これであとはアップロードするだけです！！

### 最終的

```go
func (s S3Service) UploadToS3(imageBase64 string, fileExtension string) error {
	// 環境変数からS3Credential周りの設定を取得
	var env Env
    bucketName := "バケット名"
	_ = envconfig.Process("", &env)

	sess := session.Must(session.NewSession(&aws.Config{
		Credentials: credentials.NewStaticCredentials(env.S3AK, env.S3SK, ""),
		Region:      aws.String("ap-northeast-1"),
	}))

	uploader := s3manager.NewUploader(sess)

	data, _ := base64.StdEncoding.DecodeString(imageBase64)
	wb := new(bytes.Buffer)
	wb.Write(data)

	res, err := uploader.Upload(&s3manager.UploadInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String("ファイル名" + "." + fileExtension),
		Body:   wb,
        ContentType: aws.String("image/" + fileExtension),
	})

	if err != nil {
		fmt.Println(res)
		if err, ok := err.(awserr.Error); ok && err.Code() == request.CanceledErrorCode {
			return RaiseError(400, "Upload TimuOut", nil)
		} else {
			return RaiseError(400, "Upload Failed", nil)
		}
	}

	return nil
}

```

これでアップロードはできます！！
エラーハンドリングは今から頑張りたいです。。。
VirtualBox에서 USB 패스 스루를 사용하는 방법은 무엇입니까?

![virtualbox.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447311/bd5fb6d2-fed3-6f9b-8977-cf75f48fbe13.jpeg)

가상 머신을 사용하는 경우 VirtualBox에서 USB를 연결하는 방법을 알아야 할 가능성이 높습니다. [이 기사에서는](https://www.net-usb.com/virtual-usb/virtualbox-usb-passthrough/) VirtualBox에 연결하고 [USB Network Gate](https://www.net-usb.com) 도움말을 통해 연결된 장치를 공유하는 방법을 보여줍니다.
ノートパソコンにおけるキーボードレイアウトの重要性を周知したい

# 注意書き
技術的な記事ではないですが、ご了承ください。
半分愚痴ですが、買って後悔なされぬよう、役に立てれば幸いです。

# 経緯
Windows7のサポート終了がせまるなか、AmazonでノートPCをポチって買い替えたわけですが、
職場のPCもちょうどPCの入れ替えがあり、重要と思ったところを記載してみます。

# プログラマ目線で重視したいキーボードのポイント

| ダメなレイアウト | 何がダメか |
|:----------|-----------------|
| <b>テンキーがある</b>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/a6e09d15-51af-026c-6a85-f5d4da8a5198.png) |全体的に普段使うキーボードエリアが左に寄るため、超絶打ちづらい。typoの嵐。姿勢が変になるので<b>[体にも悪い](https://tech.nikkeibp.co.jp/it/pc/article/knowhow/20090624/1016327/)</b>。 |
| <b>Fnキー＋矢印でHome/End/PgUp/PgDn にならない</b> | スムーズに行端に移動や画面スクロールができないという精神的苦痛。付けない理由が謎。。 |
| F3がFn押しながらでないと使えない※1 | 検索がしづらい。|
| 右のEnterやshiftキーが、小さすぎる or 文字キーと完全に隣接している | typoしやすい |
| 電源ボタンがキーボードレイアウトの長方形内に収まっている | delキーと間違えて電源ボタンを押してしまう |
| キーストロークが浅い（薄さを売りにしたPCでありがち） | たまにキーが埋没する。脳が打ったと認識できない。違和感がある。 |

※1：何言ってるんだ　と思うかもですが、F3が音量Upに割り当たっていて、Fn+F3が普通のF3キーとして認識するPCを買ってしまったのです。。
レジストリ`Scancode map`いじればどうにかなりそう。
[ScanCode調べてみた](https://qiita.com/kob58im/items/b800ccce8b2f230401be)

# 対策
FnキーはOSが認識できないようなので、Windowsレジストリとかでの割り当て変更も不可のはずなので注意。
最悪、外付けのUSBキーボードを使うという手もなくはないが・・・どうにも邪魔・・・

<b>店頭で触ってみるのがよいのではないかと。</b>

# 最後に
今更だけど、Windows10入れ替えで会社で導入するPC選定する人はよく考えてね！
AWS IAMとGCP IAMの比較

##はじめに
AWS IAMとGCP IAMは同じ名前のサービスですが微妙にできることが異なるため、整理してみたいと思います。

##AWS IAM
AWSにおけるIAMは、基本的にAWSアカウント内閉じたものになります。許可を付与する対象は、IAMユーザ、グループ、ロールとなり、許可設定は、IAMポリシーで行います。IAMポリシー自体は、JSONのドキュメントでTAGやS3バケットなどのリソースをConditionとして細かく設定することができます。
これは、一つのAWSアカウントで複数システムが稼働するような環境において必要となる機能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/62a0c1bb-9cea-c448-2e1e-8b2d501752bb.png)

##GCP IAM
GCPのIAMは、以下のようなイメージになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/5270a7e9-60dd-4d4b-4783-197c5858789d.png)

認可を付与する対象は、Googleアカウント、グループ、サービスアカウントになります。AWSとの違いは、大きく分けて2つあります。

- 認可設定ですが、プロジェクトのリソースに対して任意のAPIを指定して許可する形となり、JSONドキュメントを直接記載することができません。コンディションで任意のTAGが付与されたインスタンスへの操作を許可するいったことができません。これは、サービスや環境ごとにプロジェクトを分けるというアカウント設計が前提となっているからです。
- 設定対象によって、操作する管理コンソールが異なります。Googleアカウントやグループの操作は、Adminコンソールで行います。IAMのPermissionやロール、Orgnization Policyは、GCPコンソールで行います。

GCP管理コンソールでのPermissionの付与の方法は、AWS IAMと違い一度ロールを選択してから必要なPermissionを追加する形で設定します。

IAM & Admin>Roles> Create Roleをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/d558239b-71f8-7aea-815f-c8b74e8cca0e.png)

例としてCompute Adminをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/8fbca82b-4d1c-33c4-c90b-98bcf236aa65.png)

Compute AdminのPermissionがリストアップされるので必要なPermissionを使いしてロールを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/f9ca1472-3915-84a2-711e-8bf30b122d94.png)

###GCP IAMのロール
GCPのロールは、以下の3種類が存在します。

- 基本の役割(Primitive roles)
    - GCPに最初からある役割
    - Owner,Editer,Viewerから選択できる
    - at leastな設定ができため非推奨
- 事前定義済みの役割(Predefined roles)
    - GCPが事前定義したロール
    - 細かい制御が可能
- カスタムの役割(Custom roles)
    - 新規に作成するか、事前定義済みの役割を指定してカスタマイズすることが可能

その他、GCP特有の考え方でRoleのStageというものがあります。Stageとして、Alpha,Beta,GA,Disableが設定可能です。Diableに設定されたロールは、アタッチ可能ですが、実際の認可が行われません。ユーザは、Alpha/Beta/GAのStageのロールが付与されているう場合は、Permissonが許可されますが、対象のロールがDiableになるうとこれまで行ってきた操作が拒否されます。
Alpha,Beta,GAは以下の様な使い分けが推奨されていますが、そこまで細かく気にしなくても運用可能です。

- Alpha
    - 作成時は、本番運用の準備ができていないためAlphaとする
- Beta
    - 使用してしていて、問題なければBetaとする
- GA
    - 本番利用で問題ないと判断すればGAとする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/13288688-9ec3-a1d1-663c-5324c49bae92.png)

###GCP Organizationレベルの許可
GCPコンソールの左上のドロップダウンでOrgnizationを選択して、任意のユーザにロールを付与すると、Organization配下のプロジェクト全体で利用可能になります。

##投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。
Vue.jsでWebアプリ作成してみた①

ネットでVue.jsで作成したアプリがあまりなかったので、簡単なのを作って公開しようと思います。
作成したアプリは情報検索サイトです。

## アプリの仕様
データ取得には無料APIを使用したので参考記事の
リンクを張っときます。
- topページに最新Qiita情報を表示
→ [Qiita API v2 の概要(非公式)](https://qiita.com/tag1216/items/b0b90e30c7e581aa2b00 "Qiita API v2 の概要(非公式)")
- topページに東京、大阪、名古屋の天気表示
→ [【PowerShell】Invoke-RestMethodを使って天気予報を取得してみる ](https://hosopro.blogspot.com/2017/10/powershell-invoke-restmethod.html "【PowerShell】Invoke-RestMethodを使って天気予報を取得してみる")
- topページに株価情報を表示
→ [リアルタイム平均株価取得API](https://dev.matumo.com/699/ "リアルタイム平均株価取得API")
- topページに地震情報を表示
→ [地震情報を伝えるWebアプリを作ってみた](https://qiita.com/kobotyann/items/1bd080aaeb778da47231 "地震情報を伝えるWebアプリを作ってみた")
- キーワード検索機能   ※まだ作成できていません

## アプリデザイン
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/ad8cc344-a8df-cf76-2305-6144e5c09c7d.png)
｢選択データ表示｣のプルダウンを地震情報に設定するとデータが表示されます。
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/c780cff4-47b6-6734-61f1-8a642502c1be.png)

## アプリの起動の仕方
webサイトを起動するときはchromeのセキュリティに引っかからない
ように起動させる必要があります。
[【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法](https://qiita.com/growsic/items/a919a7e2a665557d9cf4 "【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法")

 ```
"chrome.exe" --args --disable-web-security --user-data-dir --new-window "http://localhost:8080/"
 ```

クロスドメイン制約に引っかかると一部APIが動かなくなっちゃう😖😖😖
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/0894c94d-3cad-b098-d86e-12f6898f7f2d.png)
##　開発環境構築
①[Vue.jsをWindowsにインストールしてみた](https://donzoko.jp/2019/01/03/vue-js%E3%82%92windows%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/)を参考にしてVue.jsの環境作成をしてください。
②①で作成した新規プロジェクトに[github](https://github.com/kaihatutarou716/newssite1 "github")にあるsrcをコピぺします。
③npm run serveコマンドを実行します。
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/a251bc15-4fa7-ded0-fed9-93882eefdcf9.png)
④「To install it, you can run: npm install --save axios」が出た場合、下記のコマンドを実行。
npm install --save axios
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/b98d3742-8aa9-c37e-d06f-0e945769b579.png)
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/00a43c8f-d03f-db73-c394-451bd043e27b.png)
⑤④が完了したら再度npm run serveコマンドを実行します。
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/1a0725a6-768f-7fa2-9472-e5fd3658d759.png)
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487273/2e331225-8e17-609f-52a4-906fa9d1f7e1.png)
##　感想
メインとなるコンポーネントに個別に開発したコンポーネントを設置して
いく感じで画面を開発していくので、画面作成をあまりしたことがない自分でも
できました、そのうち「キーワード検索機能」を実装した第2段も記事する予定です☺☺☺
無料でいいAPIないかな～
##　ソース
ソースは[github](https://github.com/kaihatutarou716/newssite1 "github")においてあります。
【Firebase】知らなくて損した時間の取得方法【１行だったのに…】

昨日までの自分をぶん殴ってやりたい。

環境　VueCLI3.0

```store.js
actions: {
    addPost ({ getters, commit }, post) {
      if(getters.uid) firebase.firestore().collection('posts').add(post)
      commit('addPost', post )
    },
}
```




昨日までのコード

```Form.vue
methods: {
  submit () {
    var now = new Date();

    // 「年」「月」「日」「曜日」を Date オブジェクトから取り出してそれぞれに代入
    var y = now.getFullYear();
    var m = now.getMonth() + 1;
    var d = now.getDate();
    var w = now.getDay();
    // 曜日の表記を文字列の配列で指定
    var wNames = ['日', '月', '火', '水', '木', '金', '土'];
    if (m < 10) {
      m = '0' + m;
    }
    if (d < 10) {
      d = '0' + d;
    }
    this.addPost({
      created_at: (y + '年' + m + '月' + d + '日 (' + wNames[w] + ')'),
    })
  })
},
   
```
結果
<img width="329" alt="スクリーンショット 2019-09-17 19.10.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447711/943a7b04-97ee-de91-568d-9f9ac32da005.png">


今日からのコード

```Form.vue
methods: {
  submit () {
    this.addPost({
      timestamp: firebase.firestore.FieldValue.serverTimestamp(),
     })
   }
 }
```

結果
<img width="329" alt="スクリーンショット 2019-09-17 19.09.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447711/28d10d2a-e7ef-ceac-af49-4438ed5fc2b6.png">


当時、ドキュメントを一生懸命探した気がするけど、節穴だったせいで今見つけた。

https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja

以上、知らなくて損した話でした。
Firefox 初期状態に戻す方法

次のリンクを Firefox で開き、記事中にある「 Firefox をリフレッシュ 」ボタンを押すと、

https://support.mozilla.org/ja/kb/refresh-firefox-reset-add-ons-and-settings

アドオンや設定のリセットができます。

ただし、ブックマークや履歴、保存されたパスワードなどは削除されないので、

いつものように、設定ページを開いて、消していく必要があるようです。
Macでbyobuを使った場合にセッションが復元されない問題

Macでbyobuコマンドを使うとエラーが出たので解決策を記録

# 結論

バージョンを5.128以上にあげる

これだけなので、以降気になる人だけどうぞ

# 環境

```
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G95
$ byobu --version
byobu version 5.127
```

# エラー内容

1. byobuコマンドでセッション開始
1. byobuを実行しているターミナルを閉じる
1. 再びbyobuコマンドでセッションを復元(あるいはターミナルをもう一個開いてbyobu)


としようとした場合に以下のエラーが出る

```
/usr/local/bin/byobu-select-session: /usr/local/Cellar/byobu/5.127/lib/byobu/include/select-session.py: /usr/bin/python3: bad interpreter: No such file or directory
/usr/local/bin/byobu-select-session: line 24: /usr/local/Cellar/byobu/5.127/lib/byobu/include/select-session.py: Undefined error: 0
```

# 原因

```
/usr/local/bin/byobu-select-session: /usr/local/Cellar/byobu/5.127/lib/byobu/include/select-session.py: /usr/bin/python3: bad interpreter: No such file or directory
```

と言われているので`/usr/bin/python3`がないのが原因のようです
なんでそのファイルを見に行こうとしているかと言うと、既存のセッションを取得するスクリプトのshebangで`/usr/bin/python3`が指定されているので、このパスを見に行ってエラーが出ているみたいですね
 
```bash
$ head /usr/local/Cellar/byobu/5.129/lib/byobu/include/select-session.py
#!/usr/bin/python3	
#
#    select-session.py
#    Copyright (C) 2010 Canonical Ltd.
#    Copyright (C) 2012-2014 Dustin Kirkland <kirkland@byobu.org>
#
#    Authors: Dustin Kirkland <kirkland@byobu.org>
#             Ryan C. Thompson <rct@thompsonclan.org>
#
#    This program is free software: you can redistribute it and/or modify
```




# 対策

`/usr/local/python3`にファイルが配置できれば良いんですが、macの場合は以下の通り`/usr/local/bin`配下にインストールされます。

```
$ which python3
/usr/local/bin/python3
```

shebangで固定されているので、別のパスに向けるのは無理そうです。

## シンボリックリンクを貼る(失敗)

であれば、とりあえずシンボリックリンクを`/usr/bin`に貼れば何とかなるかな?と試してみましたが、最近のMacでは禁止されているみたいです。([About System Integrity Protection on your Mac - Apple Support](https://support.apple.com/en-us/HT204899))

```
$ sudo ln -sf /usr/local/bin/python3 /usr/bin/
ln: /usr/bin//python3: Operation not permitted
```

残念

## 最新にアップグレードすれば解決した

どうしたもんかとGithubを覗いてみたら、以下のプルリクが投げられていました。

[Find python3 path via /usr/bin/env by ibnpaul · Pull Request #29 · dustinkirkland/byobu](https://github.com/dustinkirkland/byobu/pull/29)

```diff
- #!/usr/bin/python3
+ #!/usr/bin/env python3
#
#    select-session.py
#    Copyright (C) 2010 Canonical Ltd.
```

って感じで変更されており、`/usr/bin/`以外からも探してくれるそうでした。



ということで、結局はバージョンあげれば解決しました。
以下のコマンドでアップグレードすれば問題なく動作してくれました。(2019/09/17現在であれば5.129にアップグレードされるはずです)

```
$ brew upgrade byobu
==> Upgrading 1 outdated package:
byobu 5.127 -> 5.129
==> Upgrading byobu 
以降省略
```

# 参考

[Find python3 path via /usr/bin/env by ibnpaul · Pull Request #29 · dustinkirkland/byobu](https://github.com/dustinkirkland/byobu/pull/29)
[About System Integrity Protection on your Mac - Apple Support](https://support.apple.com/en-us/HT204899)
#エラー解消  MySQL → パスワードを環境変数に

DBをMySQLにしましたが､`rails db:migrate`でエラー｡

```
$ rails db:migrate
rails aborted!
Mysql2::Error: Access denied for user 'root'@'localhost' (using password: NO)
```
パスワードが設定されていないためエラーになっているようです｡

```ruby:config/database.yml
default: &default
 username: root
 password:
```
database.ymlファイルを確認｡

パスワードを設定しますが､ファイルに直書きしてしまうとGithubなどに
残した際に､パスワードが見れる状態になってしまうので､
パスワードをdatabase.ymlに直書きせずに環境変数を使うのが一般的｡
１つ目は教えてもらった方法と､２つ目は自分で見つけた方法｡


#1つ目 教えてもらった方法 

####vim開く
EDITOR="vi" bin/rails credentials:edit

####vim編集
D ２回で削除
U で戻る
:wq  で保存して終わる
インサートモード i
インサートモード終わる esc

ー # aws: 
ー # access_key_id: 123 
ー # secret_access_key: 345 
＋ database:
＋ user_name: root
 ＋ user_password: [password]   

※パスワードはMysqlのパス


####config/database.ymlを編集

```ruby:Config/database  .yml
default: &default adapter: mysql2 
encoding: utf8 
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 
- username: root 
- password: 
+ username: <%= Rails.application.credentials.database[:user_name] %> +password<%=Rails.application.credentials.database[:user_password] %> 
```

####エイリアス設定
 echo 'alias bcmysql='\''bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"'\' >> ~/.bashrc 

####ターミナル
$bcmysql
$bin/rails db:create
`db:create(configディレクトリの中にあるdatabase.ymlを読み込み，そのファイルに基づいてデータベースを作成します.)`

(Mysql立ち上げておかないとエラーメッセージ出ます｡`$mysql.server start`)

####確認

```
$mysql -u root -p
(mysqlのパスワードを求められます)

mysql> show databases;
```

```
プロジェクト名_development
プロジェクト名_test
```
２つテーブルできてたらOK｡
(抜け出しは`exit`)

#２つ目 Qiita記事より direnv(ディルエンヴ)

こちらはまだ試していません｡

[Mysql2で「Access denied for user 'root'@'localhost'」]
(https://qiita.com/Ushinji/items/1bd4b7f1cad87e717ac2)
AWS RDSのAurora ClusterをSystems Manager Automationで定期的に停止させる

# Clusterを停止するAutomation Documentがない

多分今後作られると思いますがなぜか AWS-StopRdsInstanceはあるのに AWS-StopRdsCluster がありません。  
となると CloudWatchの Ruleから定期的に　Cron Jobで停止することもできません。 AWS-StopRdsInstanceを参考に作成します。  

# すぐに結論  

AWS-StopRdsInstanceを参考に下記のようなDocumentを作成しました。      
結論から言うとAWS-StopRdsInstance　の　Instance を Clusterに置換、  
状態判断の JSONの  PropertySelector を　DBInstanceStatus ではなく Status にするだけで適用可能です。  


```
---
description: Stop RDS instance
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
parameters:
  ClusterId:
    type: String
    description: (Required) RDS Cluster Id to stop
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
    default: ""
mainSteps:
  -
    name: AssertNotStopped
    action: aws:assertAwsResourceProperty
    isCritical: false
    onFailure: step:StopCluster
    nextStep: CheckStop
    inputs:
      Service: rds
      Api: DescribeDBClusters
      DBClusterIdentifier: "{{ClusterId}}"
      PropertySelector: "$.DBClusters[0].Status"
      DesiredValues: ["stopped", "stopping"]
  -
    name: StopCluster
    action: aws:executeAwsApi
    inputs:
      Service: rds
      Api: StopDBCluster
      DBClusterIdentifier: "{{ClusterId}}"
  -
    name: CheckStop
    action: aws:waitForAwsResourceProperty
    onFailure: Abort
    maxAttempts: 10
    timeoutSeconds: 600
    inputs:
      Service: rds
      Api: DescribeDBClusters
      DBClusterIdentifier: "{{ClusterId}}"
      PropertySelector: "$.DBClusters[0].Status"
      DesiredValues: ["stopped"]

```

# 結論
  
これをCloudWatchの　Ruleに仕込んで Cronで起動すれば終了です。  
その内AWSで提供されるようになるのでは… 　　
というかなんで作らないのか… 

# 参考資料  

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-aws-apis-calling.html
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-actions.html#automation-action-executeAwsApi
https://docs.aws.amazon.com/en_pv/AmazonRDS/latest/APIReference/API_DescribeDBClusters.html
https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_StopDBCluster.html
PCBGoGoで中国受取とする方法

PCBを作るワークショップをやっているのですが、深センで受け取りたいという要望が増えてきました。
日本語が使えるPCBGoGoは便利ですが、深センの住所を指定することができません。
後でメールなどで深センの住所を連絡することになりますが、それまでに発注と支払いを終わらせておく必要があります。

ここではその方法を説明します。

PCBGoGoのサイトです。

![Screenshot from 2019-09-17 17-29-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f4ca20bc-2e65-f270-a380-9fa062b7f826.png)


まず、ログインします。「プリント基板サービス」から必要なデータを入力していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/79314c54-0572-535a-2efe-585ada41fe38.png)

以下のものだけ指定します。あとはデフォルトで。

-外形寸法
-枚数
-板厚 通常は1.6mm
-レジスト色
-シルク色
-表面処理

「見積作成」を押します

![Screenshot from 2019-09-17 17-25-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/06e60d47-6d67-4e5b-178a-6f55244f113c.png)

「送料」がDHL、JAPANになっているのを
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5af7a7a0-1b84-fe44-1bbf-da02b57033c1.png)

SF-Express 、CHINA,PEOPLES REPUBLIC に変更し、「カートに入れる」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/26f25d55-06dd-605e-498c-32906f79e300.png)

ガーバーデータをファイル指定し、「アップロード」してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/28ee94f0-23d5-bd04-df10-7d12494a2f14.png)

「データ確認中」が「支払い待ち」になったら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/42c6f520-1c11-9bbc-12c6-11b3316120c5.png)


支払いをします。住所は中国住所で！
曹元元(河野) 手机号码: 13480594123 所在地区: 广东省深圳市福田区华强北街道华航社区华强北路1019号华强广场B座7层华强北国际创客中心A区19号房
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/53aea029-0e76-97e9-62f5-4471b31647fa.png)


その後、注文番号をメールで送って、送ってもらいたい中国の住所をメールで送ります
enzymeでshallowやmountしてきたcomponentの中身を調べたいとき

`debug()` を使ってください。

```js
const wrapper = shallow(<MyComponent />);
console.log(wrapper.debug());
```

出力

```html

<MyComponent>
  <Button>ボタン1</Button>
  <Button>ボタン2</Button>
</MyComponent>
```

同じようなメソッドに `html()`　がありますが、抽出される要素が複数あるとエラーになります。

```js
const wrapper = shallow(<MyComponent />);
console.log(wrapper.find('Button').html()); //エラーになる
// Method “html” is meant to be run on 1 node. 2 found instead.
```

`debug()`を使ってください。
抽出されたものが全部出ます。

```js
const wrapper = shallow(<MyComponent />);
console.log(wrapper.find('Button').debug());
```

出力

```html
<Button>ボタン1</Button>

<Button>ボタン2</Button>
```

２ヶ月前に知りたかった。

参考
https://airbnb.io/enzyme/docs/api/ShallowWrapper/debug.html
[Ruby]配列を使用する際に便利なメソッドのあれこれ

#発想の選択肢を広げる組み込みメソッド
業務でコードを書くようになり、`Ruby`の便利なメソッドが次々に出てくることに驚いている。

メソッドを覚えていないのでその都度毎回調べて適用できそうなものを使用していくことがしばらく続くと思われるのですが、覚えていないにしても選択肢としての自分の中の引き出しを作っておきたい。

引き出しがないと「〇〇したいから〇〇メソッドを使えばいいか、そのメソッドどうやって使うんだっけ」
という段階にすらいかないという危機感が生まれたので頻出そうなものをメモ程度に吐き出します。

きりがなさそうなので、とりあえず配列に関わりそうなものを。。

#とりあげるメソッド

- sample
- values_at
- assoc
- compact
- uniq
- sort
- transpose
- zip
- sum
- flatten,flat_map
- Array

#要素取得系

##sampleメソッド
配列からランダムに1つの要素を取り出す。
テストケースで配列の中からランダムに一つ実行させたいときとか使えそうな気がする

```rb
[1, 2, 3, 4, 5 ,6].sample
 #=> 5
[1, 2, 3, 4, 5 ,6].sample(3)
 #=> [4, 6, 3]
```
##values_atメソッド
配列から不連続の複数の値を取り出せる。

```rb
ary = ['Apple', 'Orange', 'Strawberry', 'Banana']
a, b, c = ary[0], ary[1], ary[4]
```
こうしてたのを次のようにできる。

```rb
ary.values_at(0, 3, 4) #=> ["Apple", "Banana", nil]
```

##assocメソッド
特定のキーを持つ要素を返す。アソシエーション。
ハッシュにしておけば簡単に指定して取り出せる。

```rb
ary = [[:Apple, 100], [:Orange, 50], [:Strawberry, 200]]
ary.assoc(:Orange) #=>　[:Orange, 50]
```

#配列の整形
##compactメソッド
`nil`の要素を取り除いた配列を新しく生成。
どういうときに使うのかイマイチ例が浮かばないけど、
配列の中のnilいらん！ってなったら`compact`を使うと覚えておくことにする。

```rb
[1, nil, 'abc', false].compact #=> [1, "abc", false]
```

##uniqメソッド
重複をなくすメソッド。
色んな角度から条件を満たしていくものを配列にバンバン格納していき、最後に`uniq`をつけて重複を無くすといった使い方ができそう。便利。

```rb
[1, 1, 2, 2, 3, 4].uniq　#=> [1, 2, 3, 4]
```

##sortメソッド

順番を整えるメソッド

```rb
[5, 2, 6, 3, 1, 4].sort #=> [1, 2, 3, 4, 5, 6]
['a', 'd', 'b', 'c'].sort #=> ["a", "b", "c", "d"]
```

#ハッシュ化
##transposeメソッド
配列を行列に見立てて行と列の入れ替えを行う。
それぞれの配列番号がちゃんともう一方に対応したものであれば簡単にハッシュ化できる。

```rb
ary = [['Apple', 'Orange', 'Strawberry'],[100, 50, 200]]
ary.transpose #=>　[["Apple", 100], ["Orange", 50], ["Strawberry", 200]]
ary.transpose.to_h #=>　{"Apple"=>100, "Orange"=>50, "Strawberry"=>200}
```
##zipメソッド
ハッシュ化でもとの配列が別々なら、`zip`してしまえばいい。

```rb
product = ['Apple', 'Orange', 'Strawberry']
price = [100, 50, 200]
p product.zip(price) #=>　[["Apple", 100], ["Orange", 50], ["Strawberry", 200]]
p product.zip(price).to_h #=>　{"Apple"=>100, "Orange"=>50, "Strawberry"=>200}
```

#その他便利そうなやつ
##sum
数値だけでなく文字列もくっつけてくれる。
初期値を引数に与えることができる。

```rb
[1, 2, 3, 4].sum(5) #=>　15
['foo', 'bar'].sum('>>') #=>　">>foobar"
['foo', 'bar'].sum('') #=> "foobar"
```
配列の配列を連結することも可能とのこと。（この引数は初期値とは別かな??）
配列の平坦化。

```rb
[[1, 2], [3, 1, 5]].sum([]) #=>　[1, 2, 3, 1, 5]
```
##flattenメソッド

平坦化はこれが一般的。(可読性考えるとこっちのが楽)
入れ子になった配列を平坦にした新しい配列を返す。

```rb
[[1,2],[3,4]].flatten #=> [1, 2, 3, 4]
```

`flat_map`っていう`map`の機能に平坦化をつけたメソッドもあるみたい。

```rb
ary = ['Dog is Animal', 'chicken is bird']
ary.map { |s| s.split(' ') } #=> [["Dog", "is", "Animal"], ["chicken", "is", "bird"]]

ary = ['Dog is Animal', 'chicken is bird']
ary.flat_map { |s| s.split(' ') } #=> ["Dog", "is", "Animal", "chicken", "is", "bird"]
```

##Arrayメソッド
引数のオブジェクトが`to_ary`メソッドまたは`to_a`メソッドを持っていればその結果を、持っていなければオブジェクトを配列に入れて返す。

つまり

- `nil`なら空の配列を返す
- 配列は配列のまま返す
- 数値や文字列であれば、それを要素とする配列を返す

```rb
Array(nil) #=> []
Array([1, 2, 3]) #=> [1, 2, 3]
Array(1) #=> [1]
Array('abc') #=> ["abc"]
```

引数に配列を渡したい！といったときにわざわざ条件分岐しなくても`Array`メソッドにつっこんでおけば、どんな形であろうと配列にしてくれるということか。便利。

#まとめ
使い方やそのメソッドの挙動を確認することはよくしていたが、実際にそのメソッドがどんな場面に使われるかを想像することは今まであまりしてこなかった。
経験が足りないため、使用例がイメージできないことのほうが多いが、今後も実際に使うことをイメージしながら学習を進めていきたい。
VBAのIIFは絶対使わないほうが良い

#iifはショートサーキットではない
iifはショートサーキットではないため、
条件式が真であろうと、偽であろうと、どちらの処理も実行します。

ショートサーキットとは何者か、ついこの間知りました。
（得た知識をすぐ使いたがるやつ。）

要は条件式の結果がtrueであろうとfalseであろうと
条件式の中身を全て処理しちゃいます。

そんなコード怖すぎるぞ。


#こんな処理になります
```
Dim a As String
Dim b As String
Dim c As String

a = "1"
b = "1"


c = IIf(a = "1", IIf(b = "1", MsgBox("true"), MsgBox("false")), MsgBox("false"))

MsgBox(c)
```

iifで条件式を書きました。
自分でも何がしたいのかよく分からなくなる条件式です。

「c」にiifの結果（trueかfalseか）を入れてメッセージボックスで出すのが目的です。

結果は
とにかく全てメッセージボックスが表示されます。

msg「true」 → 「false」 → 「false」 → 「false」

ちなみに最新バージョンのコンパイラでコンパイルすると
コンパイルエラーになりました。

もうIIFはダメっぽいです。
Rails 定数を管理するsettings.yml・環境ごとの定数管理の方法

##はじめに
先日初めて、`config`下の`settings.yml`に定数を設定し、同時に環境ごとの定数も設定しました。
呼び出し方や使い方など、備忘録として纏めます。

##なぜsettingsに定数を設定するか
管理を楽にして、変更があった際に対応しやすくするためでしょう。
例えば、もうすぐ変わる消費税率で考えてみます。いろんなファイルに、`tax = 8`など別々に定義されていたら、修正するのが大変です。修正漏れも起こるかもしれませんね。

##実際にsettingsに書いてみる
ファイルの配置場所は`api/config`下になります。

```config/settings.yml
#こんな感じで書きます
api_version: '1.0.0'
user:
  minimum_voting_age: 18
  minimum_smoking_age: 20
include_tax:
  to_go: 1.08
  eat_in: 1.10
```

##定義した定数を呼び出してみる
`rails c`でコンソールを起動。

```ruby

[1] pry(main)> Settings.api_version
=> "1.0.0"
[2] pry(main)> Settings.user.minimum_smoking_age
=> 20
[3] pry(main)> Settings.include_tax.to_go
=> 1.08
```

`Settings.〜〜.〇〇`で呼び出せます。

##環境ごとに定数を設定する
urlやリンク先など、環境ごとに定数を変更したいときは```config/settings```下に`環境名.yml`を作成します。
開発環境であれば```config/settings/development.yml```、ローカル環境であれば```config/settings/localhost.yml```等になります。
書き方は`settings.yml`と同様ですが、環境ごとのファイルに定数を設定していきます。

```config/settings/test.yml
#テスト環境
web_base_url: example.hoge.jp
```

```config/settings/development.yml
#開発環境
web_base_url: http://dev.hoge.jp
```

コンソールで確認してみましょう。`rails c 環境名`で環境ごとのコンソールに入れます（Rails 6からはできなくなるそうですが...）

```ruby:test環境
#rails c testでテスト環境のコンソールに入りました
[1] pry(main)> Settings.web_base_url
=> "example.hoge.jp"
```

続いて開発環境へ。

```ruby:development環境
#rails c developmentで開発環境のコンソールに入りました
[1] pry(main)> Settings.web_base_url
=> "http://dev.hoge.jp"
```

別々の定数が定義されていると確認できました！

##まとめ
・定数を定義する際はsettingsを使うと便利
・すべての環境で共通の定数は`config/settings.yml`に。
・環境ごとに定数を設定したい場合は`config/settings/環境名.yml`に。

phpも時々触るようになったのですが、`config/config.php`、`config/環境名/config.php`に定数が設定されていました。
間違っている点等あればご指摘いただけますと幸いです。
pythonで"Unable to access file: No such file or directory"

## 現象

hoge.pyがカレントディレクトリに存在しているにも関わらず、

```
$ python3 hoge.py
$ Unable to access file: No such file or directory
```

と言われる。

## 原因

アクセスできていないのは、hoge.pyではなく、「hoge.pyスクリプト内でアクセスしようとしているファイル」。画像とか。

## 対処
スクリプト内のファイル名を指定している箇所で
・拡張子忘れ
・拡張子違い（.jpgと.JPGなど）
・ファイルパス
等の間違いがないか確認する


## 判別
そもそも.pyファイルが無いときのエラーメッセージは

```
python3: can't open file 'hoge.py': [Errno 2] No such file or directory
```

なので見分けがつく。
Redis Labsについて調べたメモ

GAE/Goの1.11でmemcachedを使おうと思ったところ、memcacheは使えなくなっており、Redis Labsを使うように推奨されていた。

[App Engin GO SDKからの移行](https://cloud.google.com/appengine/docs/standard/go111/go-differences#migrating-appengine-sdk)

ちなみに、GAEから[cloud memory store](https://cloud.google.com/memorystore/?hl=ja)を使いたい場合、現在サーバレスVPC経由でつなぐ必要がある。2019年9月現在、USとEUリージョンしかサーバレスVPCが使えないので、AsiaにGAEが立っている場合は memory storeは使えません。

[Cloud Memorystore for Redis インスタンスへの接続](https://cloud.google.com/memorystore/docs/redis/redis-overview?hl=ja#connecting)


## Redis Labsとは
[Redis Labs](https://redislabs.com/redis-enterprise/technology/highly-available-redis/)

- RedisをCloudで使うことができるDBaas
- 可用性99.999%、200M ops/sec, sub millesec latency をうたっている。


## プラン
- CloudプランとSoftware(オンプレ)プランがある
- Cloudプランは EssentialプランとProプランがある
- ProプランではActive-Active Geo Distributionプランや、Redis-on-Flash機能などの高機能がある。特に高機能を求めているわけではなく、普通にRedisをクラウドで使いたいという場合はEssentialで充分。

[プラン](https://redislabs.com/redis-enterprise/deployments/)

### Essentialsプラン

- EssentialのプランにはさらにCacheプラン、Standardプラン、Multi-AZプランがある。

#### Cacheプラン
単純なキャッシュ機能として使うことを前提とされているプラン。不具合でプロセスが落ちたり、インスタンスが不具合になった場合には、データはなくなる。

#### Standardプラン
いわゆるRedisっぽい使い方。
レプリ機能や自動failover機能、永続化機能があり、インスタンスが落ちてもエラーとはならない。

#### Multi-AZプラン
その名の通りmulti-AZでインスタンスが準備され、AZまたいだ自動Failoverがされる。
Standardプランよりさらに高い可用性となる。可用性99.999%っていうのはこのプランで初めて達成されるのかな。。

[エッセンシャル](https://redislabs.com/redis-enterprise/essentials/)


## 機能について
Essentialsプランについてさらに深ぼる。

[Essentials doc](https://docs.redislabs.com/latest/rc/)

### クイックセットアップ
[リンク](https://docs.redislabs.com/latest/rc/quick-setup-redis-cloud/)

### クラスタリング
メモリ容量のオプションをPay-As-You-Go設定にすると Redis Cloud Essentials Clusteringが有効になる。今回は数MBのキャッシュサーバーとして使うだけなので関係なさそう。

https://docs.redislabs.com/latest/rc/concepts/clustering-redis-cloud/

## データ消去ルール
設定可。

https://docs.redislabs.com/latest/rc/concepts/data-eviction-policies/

## 永続化
Redisが不具合おこしプロセス止まった場合に、永続化したデータから復旧が可能。

AOF方式(ファイル書き込み)とSnapshop方式(RDB書き込み)の2種類の方法が選べる。

- 書き込み毎にAOF -> 安全だけど、書き込み頻度が多くオーバーヘッド大きい
- 1秒毎にAOF -> 1秒以内のデータはロスする可能性がある、上よりましだがこちらもオーバーヘッドあり
- 定期的(1, 6, 12時間)にsnapshop作成 -> 定期以内のデータはロスする可能性があるが、オーバーヘッドは少ない。snapshotのほうがファイルよりリカバリがはやい。

https://docs.redislabs.com/latest/rs/concepts/data-access/persistence/

## GAEで軽く使ってみたとき思ったこと

- 無料枠だとコネクション数上限が30とかで、結構トラフィックのあるGAEから使おうとするとすぐにコネクション上限に達するので気をつける
- GCP + Redis Labs だと multi AZ プランがないので、どの程度の可用性なのがちょっと不明で怖い
CircleCIでLaravelのPHPUnitを実行した後のログをダウンロードできるようにする

# CircleCIでLaravelのPHPUnitを実行した後のログをダウンロードできるようにする

表題にはLaravelのPHPUnitと書いているが、他のケースでも使えるテクニック。

CircleCIでPHPUnitを実行するのはすでに設定できている前提とする。

ログファイルが見えると、Featureテストで落ちた時などにエラー内容を確認できてとっても便利。

## config.yaml編集

```diff:.circleci/config.yaml
(省略)
jobs:
  test: 
    docker:(省略)
    environment:(省略)
    working_directory: (省略)
    steps :
      - checkout
       (省略)
      # PHPUnit実行
      - run: php ./vendor/bin/phpunit -d memory_limit=512M	
      
      # 以下を追加する
+      - store_artifacts: 
+          path: ./storage/logs
```

## CircleCIのテストの実行結果からログをダウンロードする

CircleCIでテストの実行結果画面を表示します。

![スクリーンショット 2019-09-17 18.11.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/0da1cff0-54e6-2895-f30f-156bb7c84769.png)

Artifactsタブでファイルをダウンロードできます。
（最近CircleCIのUIが新しくなったようです。）

## 参考

https://circleci.com/docs/2.0/artifacts/

以上