OmniAICreator/Qiita-1.07M huggingface dataset:
【VBA】フォルダパスを指定してフォルダを一括で作成する（Dir、MkDir使用）

##フォルダパスをシートに入力する
同じような名前のフォルダを大量に作成する際に使用しました。
シートに以下のように入力された新フォルダパスを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700414/223d5af9-485c-6cbd-7de4-eb0c5b61c9b6.png)

作成フォルダの入力は手動でパスをコピーして入力でもいいですし、
[【VBA】ダイアログで選択したフォルダのパスをセルに入力する](https://qiita.com/KaoTechBlog/items/d2a80a251baf00221c60)
の機能をつけてもいいと思います。

##エラーの種類
######作成フォルダが存在しない
エラー文言： "（作成フォルダパス）が存在しないため作成しませんでした"
######新フォルダが既に存在している
エラー文言："新フォルダは既に存在しているため作成しませんでした"
######その他何らかのエラー
フォルダに使用できない文字、256文字以上のパス、webフォルダなどの場合のネットワークエラーなど
エラー文言："指定されたパスに何らかの不正があります"

##コード
今回は`Dir`を使用してフォルダの存在確認など行っていますが
`FSO`でやってもいいですね。

```VB
Public Sub btnMakeFld_Click()
    If MsgBox("フォルダを作成しますか？", vbYesNo + vbQuestion, "確認") = vbYes Then
        '「はい」を選んだ場合処理開始
        Dim LastRow As Long '新フォルダ最終行格納用
        LastRow = FldSheet.Cells(Rows.Count, 3).End(xlUp).Row '最終行格納
        '処理結果を最終行までクリア
        FldSheet.Range(FldSheet.Cells(4, 2), FldSheet.Cells(4, LastRow)).ClearContents

        Dim MainFld As String '作成フォルダパス格納用
        Dim NewFldPath As String '新フォルダパス格納用
        Dim i As Long
        For i = 2 To LastRow
            MainFld = FldSheet.Cells(i, 1).Value '作成フォルダパス格納
            NewFldPath = FldSheet.Cells(i, 3).Value '新フォルダパス格納
            '行番号、作成フォルダ、新フォルダを引数として渡してフォルダ作成マクロ呼び出し
            Call FldProcess.MakeFld(i, MainFld, NewFldPath)
        Next i
        MsgBox "処理が完了しました ＼(´∀｀)／" & vbCrLf & _
               "処理結果を確認してください。"
     Else
      '「いいえ」を選んだ場合処理中止
        MsgBox "処理を中断します　(>_<)"
    End If
End Sub
```

```VB
'=========================================
'フォルダ作成処理
'=========================================
Public Sub MakeFld(i As Long, MainFld As String, NewFldPath As String)
'＝＝＝＝作成フォルダが存在してるか確認
    Dim MainFldChk As String '1階層前のフォルダ存在確認用
    MainFldChk = Dir(MainFld, vbDirectory) '作成フォルダの存在確認
    If Len(MainFldChk) <> 0 Then
'＝＝＝＝新フォルダが既に存在してるか確認
        Dim NewFldChk As String
        NewFldChk = Dir(NewFldPath, vbDirectory) '作成フォルダの存在確認
            If Len(NewFldChk) = 0 Then '新フォルダが存在しなけMainFldば
                On Error GoTo eh
                MkDir NewFldPath '新フォルダを作る
                On Error GoTo 0
                FldSheet.Cells(i, 4).Value = "〇" '成功として〇を記載
            Else ''新フォルダが存在したらエラー内容を処理結果に書き込み
                FldSheet.Cells(i, 4).Value = "新フォルダは既に存在しているため作成しませんでした"
            End If
'＝＝＝＝
    Else '作成フォルダが存在しなかったらエラー内容を処理結果に書き込み
        FldSheet.Cells(i, 4).Value = MainFld & "が存在しないため作成しませんでした"
    End If
'＝＝＝＝
    Exit Sub
eh: '処理中に予期せぬエラーが起きたらここにスキップしてエラー内容を処理結果に書き込み
    FldSheet.Cells(i, 4).Value = "指定されたパスに何らかの不正があります"
End Sub
```
【実行結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700414/eb0cb514-24c2-01f6-fdf5-b6a44058470f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700414/4b169761-9c8f-29d7-0a4a-d1e494b801ff.png)
ローカルだと一瞬でたくさん作成出来ます。
社内のwebフォルダ上ではもう少し時間がかかるのと、ネットワークが途切れたりするのが原因なのか、`MkDir`でエラーになることがまれに起こりました。
もう一度やり直すと正常に作成できるので、そのようなエラーが起きた場合は再度実行するようにしました。

##ワタシ流こだわり
ファイルやフォルダを扱う際にDir派とFSO派に別れますがワタシはどっちも使ってます。
`FSO`のほうが回避できるエラーも多く利点も多いのかも。
存在確認だけとかならめんどくさいので`Dir`で済ましてしまいます。

別の機会に`FSO`を使ったファイル操作のコードを書き残したいと思います。
Mac標準のメモ帳でチェックリストを作る方法

![スクリーンショット 2020-09-15 11.40.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183835/d5509701-0827-d4cb-359e-b3c5426dd1ae.png)

mac標準のメモ帳は、軽いし、フォント綺麗だし、チェックリストも作れて最高！
laravelでbootstrapテンプレートを使うときに学んだメモ

ビューファイルは、resources/viewsの中に入れることで読み込む。

css,jsなどは、publicに入れることで読み込む。

htmlファイルは、.blade.phpに変換することで@csrfなど直接phpコードを書き込む事ができる。
※ .phpではダメで、.blade.php出ないと@csrfなどは使う事ができない。

bootstrapテンプレートなどを使ってlaravel使う場合は以下のようになる。

1. DLしたテンプレートをプロジェクト内に入れる。
2. テンプレート内のviewファイルをresources/viewsに入れる。
3. 残りを全てpublicに入れる。
4. htmlファイルを、.blade.phpに変換する。
4. 要らないファイルなどがあれば整理する。
5. ディレクトリ階層が変わるので、viewのimgタグなどを修正する。(描画して検証にかけるとエラーを吐くのでそこを修正していくと早い)

これでテンプレートを使う事ができるはず。
ネットワーク（GRE）まとめのみ

##今回やること
IPsec絡みでGREという技術が気になっていたので、触れてみようと思います。
構築も実際してみようと思いますが、今回は時間の都合でできないので、
まとめるだけにしたいと思います。

##GREとは
GREはIPでカプセル化するL3のトンネルプロトコルです。
前回やったL2TPv3はL2のトンネルプロトコルでしたね。

前回
⇒[ネットワーク構築（L2TPv3）](https://qiita.com/nishi-infr/items/6dc4e816e706c8aeba29)

こちらもL2TP同様に暗号化の機能がありません。
なのでセキュアな環境で導入するのであれば、やはりIPsecと併用します。

理解が難しいのが、使い分けです。
GREは遠隔地同士でダイナミックルーティングが可能なようです。

マルチキャストを使用できるようで、OSPFみたいなネイバー確立に必要になってくる
マルチキャストパケットを遠隔地同士で送受信できるので、そのあたりがGREを使う大きなメリット
になりそうですね。

##まとめ
今回は概要のみをまとめました。
近々、構成図作って実際に構築してみようと思います。

コマンドもある程度調査しないといけませんね。

以上となります。
Docker on wsl2がうんともすんとも言わなくなった

# Dockerがwslから使えない
きっかけは忘れましたが、突然dockerのコマンドが動かなくなりました。
もちろん、docker-composeも同様です。

```:エラーメッセージ
ERROR: dial unix /mnt/wsl/docker-desktop/shared-sockets/guest-services/docker.sock: connect: no such file or directory
```

人によってパスの部分は違いがあると思いますが、こんなエラーが出ました。
wsl上に`/var/run/docker.sock`っていうシンボリックリンクがあって、これはdocker-desktopっていうwslディストリビューション内のソケットを指しているんですが、これがどういうわけか消えてしまっています。
Dockerを再起動してもwslを再起動しても治りませんでした。

ちなみに、Power Shellからならdockerコマンドが使えました。
wslからdocker daemonへの接続が切れているだけのよう。

# 直し方
参考：[ubuntu running under WSL2 not seeing Docker daemon at unix:///var/run/docker.sock #5096](https://github.com/docker/for-win/issues/5096#issuecomment-566143320)

wsl integrationを有効にしてDocker Desktopを起動すると、wsl内にさっきのsocketなどいろんな関連ファイルのシンボリックリンクを作成するのですが、それらが中途半端に残っているせいで再起動しても治らなかったということらしい。
ので、docker関連のファイルを全て削除します。

```bash
sudo find /usr -name "*docker*" -type l -exec rm {} +
sudo find /usr -name "*Docker*" -type l -exec rm {} +
sudo find /usr -name "*kube*" -type l -exec rm {} +
sudo rm /usr/share/doc/docker-ce-cli/changelog.Debian.gz
sudo rm /var/run/docker*
```

上記コマンドをwslで実行後、dockerを再起動すると治りました。
よかったよかった。
「重複エラー」を伝える英語フレーズ

関数に渡された値が重複していたときに投げるエラーメッセージの文言や、ユーザが入力した値が既に使われているときに出すエラー文言に使える例文英語フレーズです。

## 〜が重複しています

重複した値が許可されないことを表現するフレーズです。

* X is duplicated (Xが重複しています)
* Duplicates not allowed (重複は許可されません)
* Duplicates are not allowed in this list (このリストでは重複が許可されません)
* X is a duplicate key (Xは重複したキーです)
* Duplicated title field for the article "X" (記事「X」と重複したタイトルフィールドです)

## 〜は既に使われています

「既に使われている値のため同じ値が使えない」といったニュアンスのフレーズです。

* Username & email are already taken (ユーザ名とメールは既に取得されています)
* This email is already taken (このメールアドレスは既に使われています)
* Sorry, the product ID is already taken (申し訳ございません。このプロダクトIDは既に使われています)
* This URL is already taken! Please go back and try another. (このURLは既に使われています。戻って別のものを試して下さい。)
* Given email is already in use (与えられたメールアドレスは使用中です)
* The Service X is already present (そのサービスXは既に存在します)
* Image with the same name already exists (同じ名前の画像が既に存在します)
* A field with the name 'X' already exists in 'Y', so another field cannot be defined with the same name (「X」というフィールド名は既に「Y」に存在します。そのため、同じ名前で別のフィールドを定義することはできません)

## 〜は一意でなければなりません

ユニークなものでなればならないという意味のフレーズです。

* name is expected to be unique. (名前は一意的でなければなりません)
* Username must be unique (ユーザ名は一意的である必要があります)

## 組み合わせた表現

以上を組み合わせた表現もあります。

* Procedure record called "X" already exists. Duplicates not allowed. (「X」というプロシージャレコードは既に存在します。重複は許可されません。)
* Warning: Service with this 'X' already exists. Duplicates not allowed (警告:「X」サービスは既に存在します。重複は許可されません。)
* A DNS record for a server with name 'X' already exists. Duplicates not allowed. (「X」という名前のサーバのDNSレコードは既に存在します。重複は許可されません。)
* That keyword is already in the database.  Keywords must be unique. (そのキーワードは既にデータベースに存在します。キーワードは一意でなければなりません。)
* A Category already exists with name X, name must be unique for categories. (Xという名前のカテゴリは既に存在します。カテゴリの名前は一意である必要があります)

---

最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします:relieved:→[Twitter@suin](https://twitter.com/suin)
LaravelのdispatchNowでObject of class App\Jobs\XXX could not be converted to string

## 問題

Jobを即時実行しようとして

```php
$xxx = new XXX($param);
XXX::dispatchNow($xxx);
```

としたら

```
Object of class App\Jobs\XXX could not be converted to string
```

と怒られた。

本来paramが入ってきてほしいSQLのバインドパラメータになぜかxxxが入ってきており、それが文字列に変換できなくて怒られているようだ。

## 解決方法

```php
XXX::dispatchNow($param);
```

まじか。
dockerコマンドをsudo無しで実行する簡単設定(Linux)

Linux上でdockerコマンドをsudo無しで実行すると、以下の権限エラーが発生します。

```
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json: dial unix /var/run/docker.sock: connect: permission denied
```

デフォルトではrootの実行権限が必要なのですが、以下の手順を使うことでsudo無しでdockerコマンドが叩けるようになります。

```
# dockerユーザーグループを作成
sudo groupadd docker
# 現在のユーザーをdockerグループに追加
sudo usermod -aG docker $USER
# 変更を即反映する
newgrp docker
```

# 注釈
* ユーザーグループはインストール時に作成されているはずで本来不要なはずなのですが、公式ドキュメントに記載があったので、一応こちらにも記載しています。

# 参考
* [Post-installation steps for Linux | Docker Documentation](https://docs.docker.com/engine/install/linux-postinstall/)
【2020年版】Alibaba Cloud セキュリティホワイトペーパー 日本語版

Alibaba Cloudのセキュリティホワイトペーパーがゲット出来る場所をまとめます


|--|英語|日本語|
|:---|:---|:---|
|対象|インターナショナル|インターナショナル|
|更新日|2020/04|2020/04|
|最新バージョン|2.0|4.1|
|ダウンロード場所|[English Version](https://www.alibabacloud.com/help/en/doc-detail/42435.htm)|[日本語バージョン](https://resource.alibabacloud.com/whitepaper/2020-alibaba-cloud-security-whitepaper---the-china-gateway-version-in-japanese_1729)|

バージョン相違は翻訳回数の違いによる物かと思われます。
英語の2.0が日本語の4.1に対応していると思います。（誤りがあれば指摘してください）

中国サイトが対象となる英語版、中国語版も存在するようです。
AWS lambdaで、node httpsモジュールでpostする

AWS lambda node、標準のhttpsモジュールで、chatwork APIにpostしたいと思ったが、検索してもrequest-promiseを追加しろみたいな話しかなく、AWS lambdaの標準パッケージでサクッと試したいだけだったのにサクっといかなかった。

https://nodejs.org/api/https.html#https_https_request_options_callback
公式にはgetの記述しかないのでpostができないのか、と思ったらできた。

writeにたどりつかなかった……

（参考）
https://qastack.jp/programming/6158933/how-is-an-http-post-request-made-in-node-js

```
const https = require('https');
const querystring = require('querystring');

exports.handler =  function(event, context){
    var postMessage = 'テスト'
    var post_data = querystring.stringify({body:postMessage});
    let options = {
        host: 'api.chatwork.com',
        path: '/v2/rooms/{roomid}/messages',
        port: 443,
        headers: {
            'X-ChatWorkToken': '{X-ChatWorkToken}',
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        method: 'POST',
    };
    var post_req = https.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
          console.log('Response: ' + chunk);
          context.succeed();
        });
        res.on('error', function (e) {
        console.log("Got error: " + e.message);
        context.done(null, 'FAILURE');
        });
     });
    post_req.write(post_data);
    post_req.end();
};
```
【Unity】実機ビルドでFrameDebuggerが実行できない時の対処法

## 経緯
Android実機ビルドをしたところ、描画周りで不具合が見つかりました。
FrameDebugger[^1]を使って1ドローコール毎の処理を確認してみようと思ったら、以下のエラーに遭遇し**FrameDebuggerが起動できませんでした。** 


[^1]: UnityEditorのメニューから`Window -> Analysis -> Frame Debugger`で立ち上げます


> Failed to enable Frame Debugger on Remote Device: Frame Debugger does not support the current threading mode. Only RenderingThreadingMode.MultiThreaded, RenderingThreadingMode.LegacyJobified and RenderingThreadingMode.NativeGraphicsJobs are supported.

本記事はその備忘録です。

## Multithreaded Renderingを設定する必要あり

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/ed9b5c28-d973-b92a-0681-fec197ef916f.png" width=360 />

エラー内容にある通り、ビルド設定の`Multithreaded Rendering`にチェックを入れる必要があるようです。

## 環境

- Unity2019.4.9f1
- Pixel3XL Android10
Unityプロジェクトを Bitbucket & SourceTree で管理する方法

#Unityプロジェクトを Bitbucket & Sourcetree

Windowsで開発して、iPhone用ビルドのためにMacにプロジェクト同期させる時など、
2台以上のPCで同じUnityプロジェクトを使いたい時用。


新しいプロジェクトを作った時に、
.gitignoreを作らず大量のコミットが発生してしまうことを防ぐ
いつも忘れてて時間かかるので自分用メモ




####１．新規リポジトリの作成
　BitBucketにログインして、「Create repository」で新規リポジトリを作成
　非公開リポジトリにチェック
　READMEは要らない
　gitignoreは作成

####２．Soucetreeでクローンする
　作成したら、Soucetreeを立ち上げて、「Remote」タブからさっき作ったリポジトリを、置きたい適当な場所に「Clone」する。

####３．ローカルリポジトリができているか確認
　指定したディレクトリに.gitignoreだけがあることを確認。

####４．.gitignoreを編集する
　・Soucetreeのメニューで「リポジトリ」→「リポジトリ設定」を選択。
　・でてきたウインドウで「詳細」タブを選択。
　・リポジトリ固有の無視リストの「編集」ボタンを押して、メモ帳などで開く。
　・開いた.gitignoreを　これ→「https://github.com/github/gitignore/blob/master/Unity.gitignore 」の内容に書き換える。

####５．.gitignoreをコミット
　変更をすぐにorigin/masterにプッシュするにチェックしてコミット


####６．Unityプロジェクトを移動
　管理したいUnityプロジェクトを丸ごと、さっき作った.gitignoreがあるローカルリポジトリに移す

####７．Soucetreeでコミット
　未コミット一覧に挙がってくるので、コミットする。
　・変更をすぐにorigin/masterにプッシュするにチェック

これでUnityプロジェクトの共有必要なものだけをアップし終えたので、
あとはもう一台端末のSoucetreeからCloneできる。
【Ruby on Rails】refileでの投稿画像プレビュー機能

# 目標
![img_prev.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/bbb9c4ab-c50e-e433-7d4a-7fa3106bb429.gif)


# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

# 前提
※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

- [deviseでログイン環境構築](https://qiita.com/japwork/items/275110b810965fbdf72f)
- [ログインユーザーのみができる投稿機能](https://qiita.com/japwork/items/8dfb52121036791ac4fb)

投稿機能が既にできていると仮定して進めます。

# 流れ
1 gem refileの導入
2 カラムの追加
3 modelの編集
4 controllerの編集
5 viewの編集

# gem refileの導入
```rb:Gemfile
gem 'refile', require: 'refile/rails', github: 'refile/refile'
```
<details><summary>補足</summary>
refileは、ファイルをアップロードできるようにするgemです。</details>

```:ターミナル
$ bundle install
```

# カラムの追加
```:ターミナル
$ rails g migration AddPostImageIdToPosts post_image_id:string
```
```:ターミナル
$ rails db:migrate
```
t.string "post_image_id"が追加されていればOKです。

```rb:db/schema
  create_table "posts", force: :cascade do |t|
    t.integer "user_id"
    t.string "title"
    t.string "body"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "post_image_id" # <--これがあればOK
    t.index ["user_id"], name: "index_posts_on_user_id"
  end
```

# modelの編集
```rb:app/models/post.rb
attachment :post_image
```
<details><summary>補足【refile使用のルール】</summary>
1 画像アップロードは、<%= f.attachment_field :image %>で実装
2 モデルに画像アップ用のメソッド「attachment」を追加し、imageを指定
　※今回はpost_image_idを追加したため、post_imageを指定。</details>

# controllerの編集
下記を追加することで、post_imageの変更も許可する。

```rb:app/controllers/posts_controller.rb
  def post_params
    params.require(:post).permit(:title, :body, :post_image)
  end
```

# viewの編集
今回は先にデフォルトの画像を表示させておくため、
no-image.pngという画像ファイルを事前に用意しました。
保存場所は、app/assets/imagesの中になります。

```erb:app/views/posts/new.html.erb

<% form_with,...%>
...

  <div>
    <%= attachment_image_tag @post, :post_image, fallback: "no-image.png", id: "img_prev", style: "height: 250px; width:300px;" %><br>
    <%= f.attachment_field :post_image %>
  </div>

...

<% end %>

...

<script>
$(document).on("turbolinks:load", function(){
  function readURL(input) {
    if(input.files && input.files[0]){
      var reader = new FileReader();
      reader.onload = function (e) {
        $('#img_prev').attr('src', e.target.result);
      }
      reader.readAsDataURL(input.files[0]);
    }
  }
  $("#post_post_image").change(function(){
    readURL(this);
  });
});
</script>

```
<details><summary>補足【attachment_image_tag】</summary>
refileで用意されたヘルパーメソッドで、imgタグを作成。</details>

<details><summary>補足【fallback】</summary>
何か問題が発生した際に表示する画像を指定。</details>

<details><summary>補足【turbolinks:load】</summary>
初回読み込み、リロード、ページ切り替えで動くよう設定。</details>

<details><summary>補足【Javascript動作について】</summary>
id=img_prevの属性を操作し、
changeメソッドでpostモデルのpost_imgの読み込みURLを変更</details>

<details><summary>補足【Runtime Errorが表示された場合】</summary>
エラー画面のコード上に
```Refile.secret_key = ...```
と表示されています。
そのRefile.secret_key= を含む一行をコピーし、
config/initializers/application_controller_renderer.rbの
一番下に追加すればエラーは解消できます。
</details>

# P.S.
TwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork
NXP JN516x

![IMG_20200915_101906229 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a2f05f27-f3cf-94c5-d29a-df1d93b463ef.jpeg)

JN516x は NXPのSoC。
32bit CPU で IEEE802.15.4 や Zigbee のラジオ機能がついている。

外部に電源、アンテナ線とクロック、パスコンなどのコンデンサ、若干の抵抗やインダクタだけで通信IoTのハードウェアが実現できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d2b137f8-4037-140c-343a-ad5f70b5f95c.png)

日本では、IoTモジュールである TWELITE の CPU として、JN5164が搭載されている。

# 特徴

超低電力で動作、 ZigBee, JenNet-IP, or IEEE802.15.4

https://www.nxp.com/docs/en/brochure/75017375.pdf
より抜粋

- 2.4 GHz IEEE802.15.4-compliant radio
- 128-bit AES security processor
- MAC accelerator with packet formatting, CRCs, address check, auto-acks, timers
- 2.0 to 3.6 V battery operation
- Deep-sleep current: 0.12 µA (wake-up from I/O)
- Rx current: 17 mA , Tx: 15 mA
- Receiver sensitivity: -95 dBm
- Transmit power: 2.5 dBm
- 32-bit RISC CPU, clock speed up to 32 MHz
- 4-input 10-bit ADC, comparator

# ラインナップ

| Chip	 | RAM /EEPROM/Flash | 最大送信出力 | サポートプロトコル |
|:---:|:---:|:---:|:---:|
|JN5169|	32K/4K/512K Bytes |+10dBm |ZB3, ZHA, ZLL, ZGP, IEEE	|
| JN5168|32K/4K/256K Bytes|+2.5dBm|ZB3, ZHA, ZLL, ZSE, ZGP, IEEE	|
|JN5164|	32K/4K/160K Bytes |+2.5dBm| ZB3, ZLL, ZGP, IEEE|
|JN5161|8K/4K/64K Bytes|+2.5dBm|ZGP, IEEE|


# データシートなど

JN516xシリーズ サポートリソースページ
https://www.nxp.com/products/wireless/zigbee/support-resources-for-jn516x-mcus:SUPPORT-RESOURCES-JN516X-MCUS

JN5164製品ページ
https://www.nxp.com/part/JN5164#/


データシート
https://www.nxp.com/docs/en/data-sheet/JN516X.pdf

# CPU アーキテクチャ

https://github.com/contiki-ng/contiki-ng/wiki/Platform-jn516x
によると、32-bit RISC CPU (Beyond Architecture -- BA)らしい。

Beyond Architecture というのは OpenRISC らしい
https://openrisc.io/

OPENRISC とは Wikipediaの解説(英語版)
https://en.wikipedia.org/wiki/OpenRISC 
によると、

- OpenCores コミュニティの旗艦プロジェクト
- 命令セットはシンプルなMIPSライク
- ハードウェアデザインはLGPL、モデルとファームウェアはGPL


OpenCoresコミュニティ
https://opencores.org/


Contiki-NG：次世代IoTデバイスのOSにポートされている
https://github.com/contiki-ng/contiki-ng/wiki/Platform-jn516x
Mac OS Catalinaのターミナルでtabキーを押した時の挙動が嫌な場合

Mac OS Catalinaからデフォルトターミナルがbashからzshになりました。
ターミナルでtabを押した時の挙動が変わって困っている方もいるかもしれませんので、記録に残しておきます。
zshのtabの挙動が嫌な方は、

```
setopt noautomenu
```
とするとストレスが軽減するかもしれません。

.zshrcに書いておけば、毎回打ち込む必要はありません。
Ruby学習2

# メソッドとか色々2

現在、Ruby技術者認定試験silverを取得するべく勉強中です。
言語に対する理解がまだまだなので、基本的な事からアウトプットしていきます。

# 正規表現
なぜ使うのかとか、そもそも正規表現って何？という話は割愛して、今回は模擬問題に出てきた、以下の正規表現を分解してみます。

```ruby
/^[hc].*o$/i
```
/ = スラッシュで囲まれた部分が条件
^ = 行頭の意味。$とセットの関係で、「行頭から行末まで、囲まれた範囲の条件を満たしてくださいね」という意味、だと思ってます。これが無いと、条件を満たしていない文字列が紛れてもパスしてしまう。
$ = 行末。ほぼ同上。railsにおいてはrails４以降は使えず、\Aと\zが使われる。
[hc] = []の範囲内の文字を使って良いよ。この場合はhまたはc。※ただし、後述するiの存在から、h,H,c,Cが使用可能。
.* = 何かしらの文字で0文字以上。要するに何でも良いし、文字が無くても良い。
o = アルファベットのo。※後述iの影響で、oまたはO。
i = 小文字と大文字を区別しない。

# メソッドの引数指定
まずはよく見る仮引数、実引数の指定

```ruby
def jojo(name, stand)
  p "#{name}のスタンド：#{stand}"
end

jojo("承太郎", "スタープラチナ")

=> "承太郎のスタンド：スタープラチナ"
```
仮引数が2つ有るので、実引数の数が足りないとエラーを吐く。

### デフォルト値の設定
```ruby
def jojo(name, stand = "無し") #第二引数にデフォルト値を設定する
  p "#{name}のスタンド：#{stand}"
end

jojo("ジョナサン")

=> "ジョナサンのスタンド：無し" #第二引数が無くても値が帰ってくる
```

デフォルト値から変更する事も可能。

```ruby
def jojo(name, stand = "無し")
  p "#{name}のスタンド：#{stand}"
end

jojo("ジョニィ", "タスク")

=> "ジョニィのスタンド：タスク"
```

### キーワード引数

```ruby
def jojo(name:, stand: "無し") #シンボルのように引数を設定する
  p "#{name}のスタンド：#{stand}"
end

jojo(stand: "キラークイーン", name: "吉良吉影") #実引数もキーワード指定で渡す。キーワード指定なので引数の順番は入れ替えても問題ない。

=> "吉良吉影のスタンド：キラークイーン"
```

###　キーワード引数に好きな引数を使用
任意のキーワードと値をハッシュ型で渡す事が出来る。

```ruby
def jojo(name:, stand: "無し", **z)
  p "#{name}のスタンド：#{stand}"
  p z
end

jojo(name: "ディアボロ",stand: "キングクリムゾン", dododo: "オレのそばに", gogogo: "近寄るなああーーーッ")
# キーワード指定されていないキーと値を仮引数zの中に格納

=> "ディアボロのスタンド：キングクリムゾン"
   {:dododo=>"オレのそばに", :gogogo=>"近寄るなああーーーッ"}
```

To_Be_Continued...
SSH接続でようやくパスワードなしでログインできるようになった（Git Bash for Windows使用）

さくらサーバーにWebアプリをデプロイする際に、SSH接続でログインした。
いろいろな記事を参照にして、ログインできるようになった。
ただ、最後まで解決できなかったのが、**秘密鍵のパスフレーズの省略**。
ようやく、それが解決できたので、備忘録と、他に困っている人の助けになればと思い、記事にした。

### 参考記事
- [Qiita - さくらのレンタルサーバーにSSHでログインする](https://qiita.com/non0311/items/04222771ef9aa1970f7a)
- [Qiita - ssh config](https://qiita.com/ssm_snow/items/56584b97c88d52f512d0)
- [GitHub Docs -GitHubにSSHでログインする](https://docs.github.com/ja/github/authenticating-to-github/connecting-to-github-with-ssh)
    - [SSH キーのパスフレーズを使う
](https://docs.github.com/ja/github/authenticating-to-github/working-with-ssh-key-passphrases) **←今回、パスフレーズの省略を解決したのがこの記事**

### 環境
- Windows10
- Git Bash for Windows

### 手順

#### 秘密鍵と公開鍵の作成

```
$ cd 
$ ssh-keygen
```
パスワードを求められるので、入力して忘れないようにしておく。パスワードは適切に設定しておいたほうが、セキュリティに良い。
パスワードを省略できるように後で設定する。

#### さくらサーバーに公開鍵を登録する
#####公開鍵を送る
```
$ scp ~/.ssh/id_rsa.pub hoge@hoge.sakura.ne.jp:/home/sample/.ssh/authorized_keys
```
scpコマンドにて、公開鍵がauthorized_keysとしてさくらサーバーに送られた。

##### 権限の変更
```
$ ssh hoge@hoge.sakura.ne.jp
```

でログインする。秘密鍵のパスワードを聞かれるので入力。
`Welcome to FreeBSD!`
と表示されれば、ログインできた。

ログインした状態で

```
% chmod 600 .ssh/authorized_keys
```
で権限を変更する。

#### .ssh/configを設定する
下記のように表記することで、設定したHost名でログインできるようになる。

```config:~/.ssh/config
Host sakura_server
 HostName [ユーザー名].sakura.ne.jp
 User [ユーザー名]
 IdentityFile ~/.ssh/id_rsa
```

下記のように打ってログインできるようになった。

```
$ ssh sakura_server
```

#### 秘密鍵のパスワードの省略設定
参考記事はこれ。
[SSH キーのパスフレーズを使う
](https://docs.github.com/ja/github/authenticating-to-github/working-with-ssh-key-passphrases) 

Git Bash を開いたときに、ssh-agent を自動的に実行できるようにする。

```
$ touch ~/.bash_profile
```

viやエディターに以下をコピペする。

```config:~/.bash_profile
env=~/.ssh/agent.env

agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }

agent_start () {
    (umask 077; ssh-agent >| "$env")
    . "$env" >| /dev/null ; }

agent_load_env

# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2= agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)

if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
    agent_start
    ssh-add
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
    ssh-add
fi
```

これでGitBashを開くと、1回だけ秘密鍵のパスフレーズを求められる。

これで次回以降は、パスフレーズを聞かれることなく、ログインできるようになった。シャットダウンするまでは入力不要とのこと。

やったね！！
react-apexchartsで日付を「月/日(曜日)」のフォーマットに変えたい

## 参考データ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290072/34044fb0-9764-2526-025b-425ec13a16ca.png" width="30%" />

うーん、「6/1(月)」って表示できないかな。

#### 現在のコード
```javascript
xaxis: {
  type: "datetime",
  axisBorder: {
    show: true,
    color: theme.palette.divider
  },
  axisTicks: {
    show: true,
    color: theme.palette.divider
  },
  categories: categories,
  labels: {
    format: 'MM/dd(ddd)',
    style: {
      colors: theme.palette.text.secondary
    }
  }
},
```

公式を見てみる。

### 公式情報
[Datetime ApexCharts.js](https://apexcharts.com/docs/datetime/)

んー、曜日の日本語表記はなさそう。

####　とりあえずこれで対処

```javascript
const weekday = ["日", "月", "火", "水", "木", "金", "土"];
/*
…
*/
labels: {
  formatter: function (value, timestamp) {
    var date = new Date(timestamp);
    return date.getMonth() + 1 + '/' + date.getDate() + '(' + weekday[date.getDay()] + ')';
  }
}
```

## 結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290072/24af8e9f-c3ef-bd9b-7b20-b322e6a11e01.png" width="30%" />

これで良しとする。

## 追伸
なにか他に良いコードがあればご教示いただけましたら幸いです。
Vue.jsをCDNで使う　（やることはコピペだけ！)

#簡単にいろいろなアクションやイベントを実行することができるVue.js！

そのVue.jsを簡単に導入するには、**CDN（コンテンツデリバリーネットワーク）**を使うのが最も簡単かと思います。



**CDN（コンテンツデリバリーネットワーク）とは**

CDNとは、端的に言うと、コンテンツ（ここではVue.jsのこと）を早く簡単に使えるようにできるものです。

:point_down:詳しく知りたい方はこちら:point_down:
・[https://business.ntt-east.co.jp/content/cloudsolution/column-66.html]
・[https://www.kagoya.jp/howto/network/cdn/]


では実際に実装してみましょう（コピペだけですが！）

どのページでもVue.jsを使用できるようにするには、＜head＞にCDNを挿入するだけでOK!
もしくはVue.jsを使用するhtmlページに挿入するだけでOK！

```ruby:application.html
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
</body>
```
:sunny:以上！超絶簡単ですね！:sunny:
>上記のCDNはVue.jsの最新版を毎回採用

:warning:注意点:warning:

>実際の開発現場では、バグやエラーを回避するために、バージョンを固定する場合が多い！
:point_right_tone2:本番環境での開発は、バージョンが指定されたCDNがおすすめです。

```ruby:application.html
<head>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
</head>
<body>
</body>
```


Vue.jsのCDNをググる↓
[https://jp.vuejs.org/v2/guide/installation.html]
『ランサムウェア』『Emotet』ウェビナーメモ20/9/9

ーランサムウェア新戦略
メール経由からネットワーク経由に。
1.侵入
2.内部活動（AD侵害、セキュリティ対策の無効化など）
3.ランサム感染
→データの削除のみならず、暴露の被害も考慮必要がある

◆ENEAK
露出したRDPやVPNの脆弱性よりネットワークへ侵入
◆ColdLock→（ファイルレス版）Netwalker
ADサーバ侵害（2020年台湾）
反射型DLLインジェクション

ーオークションで売られる情報。脅すことでさらに金銭要求。
◆Nefilim
◆MAZE
◆Sodinokibi /Evil

ーemotet
◆メール経由
手法：返信型メール、不正マクロ
被害：データ削除、情報窃取→横展開
◆Access as a service(AaaS)
侵入口権利の売買←摂取された情報

ー対策ポイント
1.宛名
アドレス帳の情報を利用するので、宛名等の記載に不審な点がある場合あり
2.添付マクロ
マクロを有効化する前に、送信者に確認する。
有効化することにより発動するしかけ
3.内部の対策
　サーバアップデート
4.外部への対策
　侵入・ログ監視、内部ネットワーク監視
　アクセス制限（IP..)、認証強化
　パッチ適用までの間の対策について検討...
5.手口を知る
　メール対策　
　Web対策（カテゴリ、ホワイト）
6.バックアップを取っておく


ーフィッシング詐欺
誘導されてしまう数がコロナ後増加
データの窃取（認証情報、個人情報、クラウドサービスやソフトの認証情報を狙うものが増えてる）
コロナに便乗した内容の不正サイト、法人メール

ーテレワークの弱点
1.クライアント端末の脆弱性を狙う攻撃
　新規のサービスをDLすることが多いため、不正ソフトに気がつかない
2.サービス認証情報を狙う攻撃
　認証情報を狙うフィッシングサイト
3.経路を狙い侵入する攻撃
　VPN,VDI,RDP経由での感染
[DNS]キャッシュとネガティブキャッシュの違い

## キャッシュとネガティブキャッシュの違い

- キャッシュ
DNSキャッシュサーバでは名前解決の効率を上げるために、名前解決の際に取得したデータを一時的に保持すること

- ネガティブキャッシュ
キャッシュと同様に名前解決の際に取得したデータを一時的に保持するが、
キャッシュとの違いは、`「検索対象が存在しなかった」という結果`を保持する点

## キャッシュの時間確認

- TTL値について
`キャッシュ`の説明文に記載した、`名前解決の際に取得したデータを一時的に保持すること`の`一時的`の時間を`TTL`と言います
	- TTL値が長すぎると...
		- 例えば1年間とすると、Aレコードを書き換えられても1年より長い間時間が経過しないと名前解決のデータは最新化されません。
	- TTL値が短すぎると...
		- 例えば1秒とすると、キャッシュサーバで名前解決のデータをキャッシュしているのに短期間で権威サーバにデータを取得しに行かないいけなくて、効率が悪いです。

- TTL値の確認方法

※ `digコマンド`が入ってない人は、`yum install bind-utils`で入ります。

```
dig google.com @ns1.google.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> google.com @ns1.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60825
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             300     IN      A       172.217.161.206
```

`ANSWER SECTION`の
`google.com.             300     IN      A       172.217.161.206`
300(秒)がTTL値になります。


## 参考

- [キャッシュとネガティブキャッシュって何ですか？](https://www.atmarkit.co.jp/ait/articles/1506/02/news011.html)
- [digコマンドでTTLを確認する](https://www.softel.co.jp/blogs/tech/archives/5985)
PHPickerViewControllerを使った動画の読み込み方法

# iOS14で新しく登場したPHPickerViewControllerにおける動画の読み込み方法


## PHPickerViewController
iOS14で新しくPHPickerViewControllerが追加されました。写真許可をユーザーからとる必要なく、また、OS標準の写真アプリとおなじUIで写真・動画選択ができるとても便利なものです。
[Apple Documentation](https://developer.apple.com/documentation/photokit/phpickerviewcontroller)

## 動画の読み込み

### PHPickerViewControllerの表示

```swift
func addButtonTapped(_ sender: Any) {
    var configuration = PHPickerConfiguration()
    configuration.filter = .videos
    configuration.selectionLimit = 1
    configuration.preferredAssetRepresentationMode = .current <- 動画を読み込む時のキモ
    let phPicker = PHPickerViewController(configuration: configuration)
    phPicker.delegate = self
    present(phPicker, animated: true, completion: nil)
}
```

### 動画の読み込み方法

- NSItemProviderを使います
- resultsのなかにPHAssetのassetLocalIdentifierが入っていますが、それを用いて `PHAsset. fetchAssets(withLocalIdentifiers:options:)`とやってしまうと写真許可のアラートが表示されてしまいます。
- 写真許可がいらなく動画を読み込むためにはNSItemProviderを使います。
- ここで `NSItemProvider.loadFileRepresentation(forTypeIdentifier:completionHandler:)` を使います。
- 先ほどのPHPickerViewControllerの表示のところで PHPickerConfiguration.preferredAssetRepresentationModeを `.current`に設定しておくのが大事です。ここで.currentに設定しない場合、システムがどのバージョンの動画を読み込むかの判定に時間がかかるため、数秒のタイムラグが発生します。ここで.currentを指定しておけば、1秒以内に動画を再生させることができます。 (参考: https://developer.apple.com/forums/thread/652695?answerId=629922022#629922022)



```swift
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        guard let provider = results.first?.itemProvider else { return }
        guard let typeIdentifier = provider.registeredTypeIdentifiers.first else { return }

        if provider.hasItemConformingToTypeIdentifier(typeIdentifier) {
            // not provider.loadInPlaceFileRepresentation(forTypeIdentifier: typeIdentifier) { [weak self] (url, success, error) in
            // provider.loadFileRepresentation should be used
            // PHPickerConfiguration.preferredAssetRepresentationMode should be set .current, otherwise loading takes too long
            // https://developer.apple.com/forums/thread/652695?answerId=629922022#629922022
            provider.loadFileRepresentation(forTypeIdentifier: typeIdentifier) { [weak self] (url, error) in
                if let error = error { print("*** error: \(error)") }
                if let url = url {
                    let asset = AVURLAsset(url: url)
                    // ...
                }
            }
        }
    }
```

追記) 

`provider.loadFileRepresentation(forTypeIdentifier:completionHandler:) ` だと返されるURLがtemporaryのため、completion blockを抜けた後にurlにアクセスできなくなってしまいます。もっと長い時間URLを使いたい場合は以下のようにするといいです。

```swift
provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { (url, error) in 
    if let url = url as? URL { 
        // do something with the url
    }
}
```

# サンプルレポジトリ

こちらに実際に動くプロジェクトをおいておきました。
https://github.com/justin999/PHPickerSampler
【Mac OS】PyCharmでKivyを使う！【Pythonアプリ開発】

**手順**

１、PyCharm を[ここ](https://www.jetbrains.com/ja-jp/pycharm/)からダウンロード

２、Kivyを[ここ](https://kivy.org/#download)からダウンロード

３、このままコード内でimport Kivyすると怒られるので


４、PyCharm の Preferences を開く

５、Python interpreter を新しく追加

６、Kivyを検索してインストール

これで動きます！

[もっと詳しく](http://churikeeno.blog.jp/archives/6815321.html)
【VPC】VPC・サブネットの作成

## 1. VPCを作成する
<img width="1440" alt="スクリーンショット 2020-08-13 23.08.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/81aaff5c-2601-0832-b629-4aff4863f700.png">
<img width="1440" alt="スクリーンショット 2020-08-13 23.11.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/ab006df9-6e12-74e8-73ac-b9e7b83dac89.png">

### VPC作成完了
<img width="1440" alt="スクリーンショット 2020-08-13 23.12.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/aa5a99a0-486a-8dcd-dd1d-81186448b037.png">

## 2. パブリックサブネットを作成する
![スクリーンショット 2020-09-15 9.00.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/a55e80a3-2a66-f7f2-bb21-44fd36a28977.png)

アベイラビリティゾーン：`ap-northeast-1a`
IPv4 CIDRブロック；`10.0.5.0/24`
<img width="1440" alt="スクリーンショット 2020-08-13 23.18.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/93ac8486-d106-062e-f903-cde4408770bd.png">

## 3. プライベートサブネットを作成する
アベイラビリティゾーン：`ap-northeast-1c`
IPv4 CIDRブロック；`10.0.10.0/24`
<img width="1440" alt="スクリーンショット 2020-08-13 23.23.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/1c6daa81-a558-66a4-6a1d-2078920067b4.png">

### サブネット作成完了
<img width="1440" alt="スクリーンショット 2020-08-13 23.26.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/cdd50815-c4fd-3271-ae94-45e3cdebd6b5.png">
React+TypeScriptでcanvasを用いて矩形描画する

React+TypeScriptでCanvasを用いて矩形描画をする関数コンポーネントです。

```react

import React, { useEffect, useRef, memo, FC } from 'react';

type Props = {
  canvasWidth: number; //canvas幅
  canvasHeight: number; //canvas高さ
  x: number; //矩形始点x
  y: number; //矩形始点y
  rectWidth: number; //矩形幅
  rectHeight: number; //矩形高さ
};

const Canvas: FC<Props> = ({
  canvasWidth,
  canvasHeight,
  x,
  y,
  rectWidth,
  rectHeight
}) => {
  const canvasRef = useRef(null);

  const getContext = (): CanvasRenderingContext2D => {
    const canvas: any = canvasRef.current;
    return canvas.getContext('2d');
  };

  useEffect(() => {
    const ctx = getContext();
    ctx.strokeStyle = '#000000'; // 矩形色
    ctx.lineWidth = 2; // 矩形線幅
    ctx.strokeRect(x, y, rectWidth, rectHeight); // 矩形描画
  }, [canvasWidth, canvasHeight, x, y, rectWidth, rectHeight]);

  return <canvas ref={canvasRef} width={canvasWidth} height={canvasHeight} />;
};

export default memo(Canvas);

```
Docker For Mac遅い：対策II

## 概要

以前、以下の記事で「Docker for Mac」が遅い問題を書いて見ましたが、「Docker for Mac」次第の改善は期待できず「edge」も続けて使用して見ると使えるものでもなかった認証でした。
[Docker For Macが遅い]：https://qiita.com/FattyRabbit/items/b81575ed9d2f463fa619
[Docker For Macが遅い：対策の実験]：https://qiita.com/FattyRabbit/items/bfb5a9a321718b7f2756

## docker-sync

docker-syncを試して見ました。速度はすごく効果が出ていましたが、自分が構成している[複数のプロジェクトを一個のローカル開発環境](https://fatty-rabbit.tistory.com/category/Laravel%20%2B%20Docker%20%2B%20%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83)で動かすものでしたら、監視するべきファイル・ディレクトリが多くなりすぎてその分プロセサやメモリが利用されることで上場に使用する分重くなりました。

Macのスペックが高くてリソースに余裕があった場合は良いかと思います。docker-syncの起動する時監視ファイル数が多いと時間が掛かったりします。

## 最終的な選択

以前、おもちゃとして買った「Raspberry Pi Model 3B+」に「https://bitbucket.org/FattyRabbit/docker-local-server/src/87383983182699cc83049cec7685b0d083512dfc/?at=releases%2Fphp-form_out_centos_for_raspi」をインストールして利用しました。
![raspberry-pi-model-3b+.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489182/0a9a0dbb-e85e-05a6-b9c7-c82054cc00b1.jpeg)
Raspbianで動かすために使用しているイメージの変更とかがありますが、までREADMEの更新はしてない状態ですが、「[改善された開発環境を作成](https://fatty-rabbit.tistory.com/14?category=836398)」をご参考にしたら。
【VPC】VPCとの接続

## VPCエンドポイント
本来インターネットからしかアクセス出来ないAWSのサービスに対し、VPC内部からプライベートに接続することを可能にするサービス

### 1. インターフェイスエンドポイント
サブネットにエンドポイント用のプライベートIPアドレスを生成し、DNSが名前解決でルーティングするElastic Network Interface

- アクセス制御 → セキュリティグループ
- 料金 → 有料

### 2. ゲートウェイエンドポイント
サポートされるAWSのサービス（S3, DynamoDB）を宛先とするトラフィックのルートテーブルで、ルートのターゲットとして指定するゲートウェイ

- アクセス制御 → エンドポイントポリシー
- 料金 → 無料

## NATゲートウェイ
プライベートサブネットからインターネットにアクセスする際、プライベートIPアドレスからパブリックIPアドレスにアドレス変換を行う場合に利用するゲートウェイ

- アベイラビリティゾーン単位で作成する
- AWSのマネージド型サービスなので、NATゲートウェイ自体のサーバー運用はAWSが代行する
- パブリックサブネットに作成し、Elastic IPを割り当て、プライベートサブネットのルートテーブルのターゲットにNATゲートウェイのIDを設定することで機能する

![スクリーンショット 2020-09-13 20.31.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/01c1ae88-f20d-7381-a0d8-40205af5ad60.png)

## VPCピアリング接続
2つのVPC間でプライベートなトラフィックのルーティングを可能にするネットワーキング接続
自分のVPC間、別のAWSアカウントのVPCとの間、または別リージョンのVPCとの間に作成可能
![スクリーンショット 2020-09-15 8.50.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/234ae3b8-e6f5-50e9-d0f0-b1865741fb12.png)

## オンプレミス接続
### 1. VPNコネクション
**Virtual Private Network** の略
オンプレミスネットワーク、リモートオフィス、クライアントデバイス、および AWS グローバルネットワーク間に安全な接続を確立出来るサービス

- インターネット経由で接続が確立されるため、通信品質・ネットワーク帯域幅はDirect Connectに劣る
- 通信確立までのリードタイムが短い
- 比較的費用が安い

<img width="789" alt="スクリーンショット 2020-08-13 8.55.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/dce94fe7-6b03-085e-09d7-41b458139b17.png">

### 2. Direct Connect
AWSとデータセンター、オフィス、またはコロケーション環境との間にプライベート接続を確立することが出来るサービス

- 専用線を経由して接続
- 通信品質・ネットワーク帯域幅が安定している
- 通信確立までのリードタイムが長い
- 比較的費用が高い

<img width="784" alt="スクリーンショット 2020-08-13 8.51.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/c743709d-0c50-d28b-021f-932af398236c.png">

**Direct Connect Gateway**：1つのリージョンでDirect Connect接続を確立すれば、Direct Connect Gatewayを経由することで別リージョンへのVPCへもアクセス可能
![スクリーンショット 2020-09-14 8.54.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/82f8f5ab-9996-5173-cbd3-32ac689c93e6.png)
オフライン環境構築 Ansible編

[オフライン環境構築 目次へ](https://qiita.com/kannkyo/items/1e5f8362ed591ebda33d)

# 概要

オフライン環境で Ansible を構築するための手順。

Ansible は、プロビジョニングのための構成管理ツールである。

詳細は、 [プロビジョニングツールの比較](https://qiita.com/kannkyo/items/ebfda4bd7a77053f5211) 参照。


# 手順

Ansible は Collection と Role という2つの再利用可能な構成管理単位をもつ。

1. Collection
1. Role

構成管理単位毎に、オフラインでの使用方法が異なる。

## Collection

### オンライン端末

オンライン端末で以下の手順を行う。

1. [Ansible Galaxy](https://galaxy.ansible.com/search?keywords=&order_by=-relevance&deprecated=false&type=collection&page=1) でCollectionを検索する。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/65092d14-c91e-cc92-934a-57ec339a23eb.png)

2. **Download tar ball**ボタンをクリックしてtar ballをダウンロードする。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/053ff50a-87e7-6f40-a595-c4ed457bf498.png)


### オフライン端末

オフライン端末で以下の手順を行う。

1. 以下のコマンドを実行してCollectionをインストールする。

    ```shell
    # Command
    $ ansible-galaxy collection install <collection tar ball name>

    # Example
    $ ansible-galaxy collection install sindhuparvathi_gopi-ansible_collection_template-1.0.2.tar.gz 
    ```

## Role

Role は、Collectionとは異なりオフライン用のtar ballダウンロード機能がない。

そこで、GitHubからRoleをダウンロードして、tar ballをつくる。

### オンライン端末

1. [Ansible Galaxy](https://galaxy.ansible.com/search?keywords=&order_by=-relevance&deprecated=false&type=role&page=1)でRoleを検索する。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/9818c5d1-a36c-5890-bd27-64d530c29afd.png)

2. **GitHub Repo** ボタンから、Roleのリポジトリを表示する。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/8c8fb5a4-d743-8f74-0738-1c18e9194905.png)
     出典： https://galaxy.ansible.com/geerlingguy/java

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/5e6a2581-a0fd-4758-6c6b-2687d946261d.png)
    出典： https://github.com/geerlingguy/ansible-role-java


3. **Code** ボタンをクリックして、 **Download ZIP** リンクをクリックし、ソースコードをzip形式でダウンロードする。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/83873da7-0dc6-dd94-86d7-a295b0f5fd13.png)
    出典： https://github.com/geerlingguy/ansible-role-java

### オフライン端末

1. zipファイルをtar.gzで圧縮し直す。

    ```shell
    # Command
    $ unzip <zip file name>.zip
    $ tar czvf <tar file name>.tar.gz <zip file name>/

    # Example
    $ unzip ansible-role-java-master.zip
    $ tar czvf ansible-role-java-master.tar.gz ansible-role-java-master/
    ```

2. `requirements.yml`を作成する。`requirements.yml`にRoleの名前、バージョンとRoleのtar ballとの対応関係を定義する。

    ```yaml:requirements.yml
    # Template
    - src: ./<tar file name>.tar.gz
      name: <role name>
      version: <role version>

    # Example
    - src: ./ansible-role-java-master.tar.gz
      name: "geerlingguy.java"
      version: "1.10.0"
    ```

3. `requirements.yml`を使ってRoleをインストールする。

    ```shell
    $ ansible-galaxy install -r requirements.yml 
    ```
AtCoder ABC 178 Python (A~E)

# 総括
AとBしか解けず。
自分の解けなさに愕然としつつ、淡々と問題をこなしていくしかないです。
今回は数学回（？）でした。


#問題
https://atcoder.jp/contests/abc178

# A. Not
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/106b4c4b-7602-5167-aada-86534928eb32.png)

##### 回答
```python

x = int(input())

if x == 0:
    print(1)
else:
    print(0)

```
いろいろな書き方があると思いますが、素直にif文で書きました。



# B. Product Max
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/8df2fd05-85d1-7351-13df-f641651a4bdd.png)

##### 回答
```python

a, b, c, d = map(int, input().split())
answer = 0

if a < 0 and 0 <= b:
    if c < 0 and 0 <= d:
        answer = max(a * c, b * d)
    elif 0 <= c and 0 <= d:
        answer = b * d 
    elif c < 0 and d < 0:
        answer = a * c

elif 0 <= a and 0 <= b:
    if c < 0 and 0 <= d:
        answer = b * d
    elif 0 <= c and 0 <= d:
        answer = b * d
    elif c < 0 and d < 0:
        answer = a * d

elif a < 0 and b < 0:
    if c < 0 and 0 <= d:
        answer = a * c
    elif 0 <= c and 0 <= d:
        answer = b * c
    elif c < 0 and d < 0:
        answer = a * c

print(answer)

```
if文を書いている途中で、「maxとればいけるな・・・」と思いながらも、引き返さずに全場合分けを書ききりました。
こんなに場合わけしなくても下記のようにmaxで解けば終わりです。

```python

a, b, c, d = map(int, input().split())
answer = max(a*c, a*d, b*c, b*d)
print(answer)

```


# C. Ubiquity
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/45d0990c-8ddf-f094-06c8-a8e98f0b5ba1.png)

##### 回答(後日AC)
```python

MOD = 10**9 + 7
N = int(input())

# 少なくとも0がはいる
in0 = 10**N - 9**N
# 少なくとも0がはいる
in9 = 10**N - 9**Nu
# 0または9がはいる
0and9 = 10**N - 8**N

answer = in0 + in9 - 0and9

print(answer%MOD)

```

喉元まで答えが出かかっていたのですが、なぜか回答を導き出せず。
普通に数えあげることはできないので、全体から引き算を行うことで算定します。
下記イメージ図。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/d6b3ab37-915d-1df8-f427-3133abc9690c.png)


# D. Redistribution
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/29c5511d-49d0-f88a-e4d5-8aa143002058.png)

##### 回答(後日)

```python


MOD = 10**9 + 7
S = int(input())

dp = [0] * (S+1)
dp[0] = 1
for i in range(1, S+1):
    for j in range(0, (i-3)+1):
        dp[i] += dp[j]
        dp[i] %= MOD

print(dp[S])

```

[snukeさんの回答](https://atcoder.jp/contests/abc178/submissions/16727636)そのまま。

```DP``` だなとわかったところまでしかわからず。
解説みれば、「確かにね」とわかるものの、実際に制限時間内に解けと言われると```DP```は解けないです。
修業が足りない・・・。


# E. Dist Max
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668985/81950d0f-7084-a8cf-581f-b5e28ae81763.png)

##### 回答（後日）

```python

N = int(input())

a, b = [], []
for i in range(N):
    x, y = map(int, input().split())
    a.append(x+y)
    b.append(x-y)

a.sort()
b.sort()

answer = max(a[-1] - a[0], b[-1] - b[0])
print(answer)

```

これまた、[snukeさんの回答](https://atcoder.jp/contests/abc178/submissions/16728710)そのまま。

maxの式変形は勉強になりました。
JavaScriptを学ぶ

# JavaScriptを学ぶ

## 出力
```javascript
console.log("hogehoge");
```

## 変数の定義
基本の形

```javascript
let 変数名 = 値
```

変数strに文字列のhogehogeを代入

```javascript
let str = "hogehoge"
```

変数の値を上書きすることができる
letは必要なく `変数名 = 値`で定義できる

```javascript
str = "huga"
```

上書きできない定数を定義する際には`const`を使用する
後から値を上書きすることができない

```javascript
const num = 1
```

## テンプレートリテラル
変数を文字列の中に埋め込むことができる。
その際には以下のルールがある
`バッククォートで文字列を囲む`
`変数は${}で囲む`

```javascript
let name = "佐藤"
console.log(`私の名前は${name}です');
// 私の名前は佐藤です
```

## 条件分岐

```javascript
if(条件式1){
  条件がtrueなら実行する処理
} else if(条件式2) {
  条件式2がtrueなら実行する処理
} else {
  条件式が全てfalseなら実行する処理
}

const num = 5
if(const > 0){
  console.log("0より大きい");
}
```

## 不等号

```javascript
より大きい >
以上      >=
より少ない <
以下      <=

等しい    ===
等しくない !==

かつ      &&
または     |
```

## switch文
値によって処理を分岐させたい場合に使用するのがswitch
`break`は処理をそこで中断するためのもの
このbreakがないと次のcaseの処理も実行してしまう

`default`は当てはまるcaseがない場合に実行する処理
これもbreakが必要になるので注意

```javascript
const num = 2;
switch(num){
  case 2:
    console.log("2です")
    break;
  case 3:
    console.log("3です")
    break;
  default:
    console.log("当てはまる数字はない")
    break;
}
gapiのPromiseでAngularのChangeDetectionが走らない

## 概要
例えばSpreadSheetAPIを呼ぶのに`gapi.client`を使うことがあるかと思います。**Angularで普段通りこのPromiseを受け取ってasyncPipeなり、subscribeして変数に突っ込むなりしても画面が更新されない**問題に当たりました。正しいキーワードで検索できればすぐなのですが問題がピンポイントすぎて(よもやgapiの時だけそんなことが起きると思っていなかった)時間を溶かしてしまったので、これから当たる人がすぐ気づけると良いなという気持ちでメモに残します。

## Disclaimer
※頭に置くとTwitter等のサムネの引用でDisclaimerが使われてしまうのでこの位置に挟んでいます。
<font color="DarkGray">この記事を執筆現在私はGoogleで働いています。記事内でGoogleのプロダクトについて言及するため明確に所属を記載していますが、このことは私が記事内に登場するプロダクトについて特別詳しい知識を持っていることを**意味しません。**１ユーザーが書いた記事としてお楽しみください。</font>

## 問題のコード
早速見ていきましょう。

```service.ts
  getSheets() {
    // gapi.clientがロードされたら
    return this.oauth.ensureGapiLoaded().pipe(
      mergeMap(() => {
        // SpreadsheetAPIを呼ぶ
        return gapi.client.sheets.spreadsheets.get({
          spreadsheetId: spreadsheetId,
        });
      }),
      map((response) => {
        // 欲しい形に整形する(関係ないので省略)
      })
    );
  }
```
特に変わったところはない、データを取りにいくサービスのメソッドですね。
これをコンポーネント側で普段通り使います。

```component.ts
this.service.getSheets().subscribe(res => {
    this.sheets = res;
    console.log(res); // 確認用
});
```
```component.html
<div *ngFor="let sheet of sheets">{{sheet.name}}</div>
```
こちらも普通です。ここから期待される動きは
1. サービスから値が帰ってきて変数に代入される
2. 変更が検知されて再描画される
3. 画面にSheetの名前が見える
ですね。

ところが、実際やってみると`component.ts`に値が来た時点で`console.log()`で値がきちんと表示されるにもかかわらず画面は真っ白のままです。あれれ…:anguished:

私は自分が超基礎的な何かをすっぽり忘れてしまったのかと思い色々試したのですが(ここで時間が溶けた)、部分的にmockのObservableと入れ替えて試したところ、gapiを置き換えた時は普通に画面が更新されたのでここでやっとgapiが原因だと気がつきました。

## 問題を解決するコード

一度原因に気づけばあとは検索ですぐ答えを見つけることが出来ました。
[どうやらgapiはIE対応するために独自実装されたPromiseを使っているらしく](https://github.com/google/google-api-javascript-client/issues/353#issuecomment-341560055)、これがAngularのChangeDetectionとうまく動かないようです。
GithubのIssueを上げてくれた人、回答してくれた人に感謝を捧げつつ :pray:、提案されているworkaroundを試します。

```service.ts
  getSheets() {
    return this.oauth.ensureGapiLoaded().pipe(
      mergeMap(() => {
        // Promise.resolve()でラップする
        return Promise.resolve(gapi.client.sheets.spreadsheets.get({
          spreadsheetId: spreadsheetId,
        }));
      }),
      map((response) => {
      })
    );
  }
```
これで画面がきちんと更新されるようになりました 🎉
短い記事でしたがここまでお付き合いいただきありがとうございます。
いつか誰かの役に立てば幸いです。
for文を使わずに、numpy の掛け算でやってみよう

#for文を使いたくないけど、numpyでどう計算していいかわからない

ここで扱う計算は、色々な組み合わせをかけ合わせたい場合。それ以外はほかの記事を当たってください。

```math
\boldsymbol A = \left(a_0, \dots, a_I  \right) \\
\boldsymbol B = \left(b_0, \dots, b_J  \right) \\
\boldsymbol C = \left(c_0, \dots, c_K  \right) \\

```
から

```math
a_i b_j c_k
```
を計算したい場合

```python
A = np.arange(2)+1
B = np.arange(3)+1
C = np.arange(4)+1
print("A=", A)
print("B=", B)
print("C=", C)

D = A[:, np.newaxis, np.newaxis] * B[:, np.newaxis] * C
print("\nD=", D) 
print("\nD.shape=", D.shape) 
```

```
A= [1 2]
B= [1 2 3]
C= [1 2 3 4]

D= [[[ 1  2  3  4]
  [ 2  4  6  8]
  [ 3  6  9 12]]

 [[ 2  4  6  8]
  [ 4  8 12 16]
  [ 6 12 18 24]]]

D.shape= (2, 3, 4)
```

なお、$b_j c_k$ だけであれば、`numpy.outer` で十分。

```python
print(np.outer(B,C))
print(B[:, np.newaxis] * C)
```

```
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]]
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]]
```

##ちょっと複雑な例

```math
\boldsymbol A = \left(a_0, \dots, a_I  \right) \\
\boldsymbol B = \left(b_0, \dots, b_J  \right) \\
\boldsymbol C = \left(c_0, \dots, c_K  \right) \\
\\
\boldsymbol X = \left(x_0, \dots, x_L  \right) \\
\boldsymbol Y = \left(y_0, \dots, y_J  \right) \\
\boldsymbol Z = \left(z_0, \dots, z_K  \right) \\
\\
a_i x_l \sum_{j=0}^J b_j  y_j \sum_{k=0}^K c_k z_k \\

\newcommand{\argmax}{\mathop{\rm arg~max}\limits}
\newcommand{\argmin}{\mathop{\rm arg~min}\limits}

\argmax_{j}{a_i x_l b_j  y_j \sum_{k=0}^K c_k z_k} \\

```
の場合

```python
ABC = A[:, np.newaxis, np.newaxis] * B[:, np.newaxis] * C
XYZ = X[:, np.newaxis, np.newaxis] * Y[:, np.newaxis] * Z
print("\nABC=", ABC)
print("\nXYZ=", XYZ)

O = ABC[:, np.newaxis] * XYZ
P = np.sum(O, axis=(2,3))
Q = np.argmax(np.sum(O, axis=3), axis=2)
print("O=", O)
print("P=", P)
print("Q=", Q)
```
とすればいいみたい。
OpenCVのhconcatがなぜかエラーになるとき

　表題の通りです。エラーメッセージと原因がシンプルに結びついているページがなかったので記事にしました。

　ある画像と別の画像（同じ画像でもよいですが）を連結したい時は、OpenCVの`hconcate`や`vconcat`を使うのが便利です。例えば、`hconat`（水平方向への連結）をする場合は当然、お互いの縦ピクセル数を揃える必要があるのですが、時々それを揃えた上でもなぜかエラーが出てくることがあります。

　こんな感じに。

```python:python
combined_image = cv2.hconcat([left_image,right_image])
```

```python:output
Exception has occurred: error
OpenCV(4.1.2) C:\projects\opencv-python\opencv\modules\core\src\matrix_operations.cpp:68: error: (-215:Assertion failed) src[i].dims <= 2 && src[i].rows == src[0].rows && src[i].type() == src[0].type() in function 'cv::hconcat'
```

　なんだか行列計算のサイズがあってなさそうです。リサイズを間違えたのでしょうか。`print`でデバッグします。

```python
print(left_image.shape)
print(right_image.shape)
```

```python:output
(256, 256)
(256, 256)
```

　あっとるやないかーい！

　結論的に言うと、**データの型が合っていない**のが原因です。numpyを使って合わせましょう。

```python
left_image = np.array(left_image)
left_image = out.astype('int32')
right_image = np.array(right_image)
right_image = canny.astype('int32')
```

　これで連結できるようになります。

#おまけ

　ほかありがちなエラー。

###高さが違う

　リサイズしましょう。`cv2.resize(img,(x,y))`でできます。

###画像を読み込めていない

　初歩的ですがありがちです。`imread`だとパス指定をミスっていても、エラーにならず`None`が返されるのです。`print`したら`None`になってないか確認しましょう。

###グレースケールとカラー画像を合成しようとしている

　これもありがちです。グレーの画像の方もデータ上はカラー画像にする必要があります。`cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)`でできます。
ssh鍵にメールアドレス を紐づける

# 目的

- ssh鍵の作成時にメールアドレスを紐づける方法を記載する
- ※本記事は筆者のメモ的要素が強いため簡易的にまとめる

# 方法

- 下記コマンドを実行してssh鍵作成時にメールアドレスの紐付けを行う。

```
$ ssh-keygen -t rsa -b 4096 -C メールアドレス ssh鍵ファイル設置ディレクトリ
```
合格体験記👑AWSとインフラ未経験プログラマがAWS CLFを受験してみた話

先日、AWS CLFを受験しました。
なんとか合格できたので、勉強法などまとめます。

##受験理由
###AWSを勉強したかった
もともとぽんこつプログラマーとして働いていますが、
動く理由がわからないのが嫌でした。

AWSだとインフラ面が勉強できるなぁと思ったのと、
友人がAWSを勉強しているのもあり、
とりあえずやってみようという感じで始めました。

もともとSAAを受験するつもりで進めてきましたが、
テストセンターで試験を受けたことが無いのもあり、
SAAの練習も兼ねて受験することを決断しました。

##私のスペック
・インフラ未経験
・もちろんAWSも未経験

##勉強方法

###SAA
以下の講座を一周しました。
https://www.udemy.com/course/aws-associate/

また、以下の問題集をちょこっと触りました。
ほんとにちょっと。
https://aws.koiwaclub.com/

###CLF
受験直前に、以下の問題集の基本・応用を3周しました。
~~ホンマに一夜漬けです。よくないよくない。。~~
https://www.udemy.com/course/aws-4260/

答えだけではなくて、解説も8割は覚えました。

ちなみに、正答率はこんな感じです。
1回目：4-7割
2回目：7-8割
3回目：9割

##結果

![IMG_8446.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629073/6b3f5809-d27e-6909-c387-d9a4e58981f5.jpeg)


合格しました。わーい！
ギリギリだけど・・・まあいいか・・・・・


##感想
~~テストセンターが寒いし、受験当日なぜかずっと眠くて絶望しました（）~~

試験対策が甘かったのが主な原因ですが、、、、
SAA対策がメインだったので、知らないサービスが多かったです。
初見のサービスも何個か出現したため、かなり焦りました。。

とりあえず、一発合格かつ、テストセンター慣れも出来たのでたので、目標達成です。よかった。。

SAAも受験予定なので、引き続きがんばります(*^^*)♡
railsの本番環境で開発環境と同じようにエラーを表示させる

# はじめに
・自分の知識の備忘録も兼ねています。
・間違いなどありましたらご指摘いただけますと幸いです。

# デプロイ後、本番環境でのエラー画面
![スクリーンショット 2020-09-15 6.58.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630925/673c825f-1bff-9349-bc72-3febacb78f9b.png)
開発環境とは異なるエラー画面なのでどこが引っかかってるかすぐにわからないですね。
エラーログを見る方法もあります。
わかりやすい記事があったので引用させてもらいます。

[Rails]本番環境(EC2)でエラーログを見る方法
https://qiita.com/nkekisasa222/items/d4ef64a5e6b539ed3c37

# 開発環境と同じエラー画面を表示させる
config/environments/deveropment.rbの13行目（各自の環境によって異なるかもしれません）
以下のとおりにします。

```ruby:config/environments/deveropment.rb
  # Show full error reports.
  config.consider_all_requests_local = true  # falseをtrueに書き換える
```

これで再度デプロイすると開発環境と同じエラー画面になるはずです。
ただ、ユーザーからもエラーの内容が見えてしまうため、エラー解消したら記述を元にもどしておいたほうが良さそうです。