OmniAICreator/Qiita-1.07M huggingface dataset:
iOSアプリにYoutubeプレイヤーを組み込む

アプリにYoutubeプレイヤーを組み込んで制御できます。
![IMG_1516.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/529ddb7a-7d44-7cbe-c3fa-734e68065cd2.png)

[YoutubePlayer-in-WKWebView](https://github.com/hmhv/YoutubePlayer-in-WKWebView)というオープンソースライブラリをつかいます。

[Youtube公式のドキュメント](https://developers.google.com/youtube/v3/guides/ios_youtube_helper)では
[youtube-ios-player-helper](https://github.com/youtube/youtube-ios-player-helper)が使用されていますが、これは現在Apple非推奨となっているUIWebViewを使っていますので、この記事では推奨のWKWebViewにアップグレードされた上記ライブラリを使います。

#手順

###１、CocoaPods初期化
ターミナルからアプリのディレクトリに移動して下記実行。

```shell
pod init
```

###２、YoutubePlayer-in-WKWebViewをCocoaPodsでインストール
アプリのディレクトリでPodfileを開いて下記を追記。

```shell
  # Pods for YourProject
pod "YoutubePlayer-in-WKWebView", "~> 0.3.0"
```
ターミナルから下記実行。

```shell
pod install
```
###３、PlayerViewを設置
ストーリーボードから取り付ける場合は、UIViewを置いて、カスタムクラスでWKYTPlayerViewを選びます。

```swift
@IBOutlet weak var PlayerView: WKYTPlayerView!
```

###４、インポートとデリゲート設定

```swift
import YoutubePlayer_in_WKWebView

class ViewController: UIViewController,WKYTPlayerViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        YTPlayerView.delegate = self
    }
}
```

###５、再生

```swift
playerView.loadWithVideoId("r8ZKMVIo8IE")
```
![IMG_1515.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/49f75d19-f287-b302-b9c8-286c2b10f337.png)
デフォルトは全画面↑

[再生パラメータ（playerVars)](https://developers.google.com/youtube/player_parameters?hl=ja#Parameters)で viewの範囲内だけで表示するなど、いろいろコントロールできます。

```swift
PlayerView.load(withVideoId: "r8ZKMVIo8IE",
                playerVars: ["playsinline":1, // 全画面ではなくViewの範囲内で再生。
                             "playlist":["0SJHPnRY8YA"] // 最初の動画の後に自動再生されるプレイリスト。
                ])
```
![IMG_1516.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/28558e59-d0ff-86f9-1308-74d9d54e49bb.png)
インライン再生↑

###６、再生の制御

```swift
PlayerView.playVideo() // 再生
PlayerView.pauseVideo() // 一時停止
PlayerView.stopVideo() // 停止
```

###７、デリゲートメソッド
このようなデリゲートメソッドがあります。
![スクリーンショット 2020-10-13 13.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/f0f8f9db-bd51-8f4d-7231-cfac67d09738.png)
再生時間に応じて呼ばれるメソッドや、再生画質の変化に応じて呼ばれるメソッドなどがあります。

例えば、Player表示後に自動で再生開始したい場合は、再生準備完了時に呼ばれるデリゲートメソッドを使います。

```swift
func playerViewDidBecomeReady(_ playerView: WKYTPlayerView) {
    PlayerView.playVideo()
}
```

🐣
****
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
VueでURLからハッシュ("#")を削除し、リロードもできるようにする

# 概要
Vueアプリはデフォルトでrouterのパスに「ハッシュ(#)」が含まれています。これはrouterを「historyモード」に変更することで削除することができますが、**historyモードを使用することでページをリロードした際に、404エラーが返却されてしまいます(historyモードでない場合にはこの問題は発生しません)。**

> しかしながら一点問題があります。シングルページのクライアントサイドアプリケーションなので、適切なサーバーの設定をしないと、ユーザーがブラウザで直接 http://oursite.com/user/id にアクセスした場合に 404 エラーが発生します。- [HTML5 History モード](https://router.vuejs.org/ja/guide/essentials/history-mode.html)

しかし、適切な設定をすれば「ハッシュを削除しつつ、リロードにも対応する」ことが可能となります。

# Expressをインストールする

```
$ npm install express --save
```

# connect-history-api-fallbackをインストールする

```
npm install --save connect-history-api-fallback
```

参考：[connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback)

# ルートディレクトリにserver.jsを作成する

```javascript:server.js
var express = require('express');
var path = require('path');
const history = require('connect-history-api-fallback');
var serveStatic = require('serve-static');
app = express();
app.use(history());
app.use(serveStatic(__dirname + "/dist"));
var port = process.env.PORT || 5000;
app.listen(port);
console.log('server started '+ port);
```

# package.jsonを編集する

ルートディレクトリにあるpackage.jsonに追記します。

```diff:package.json
{
  "name": "＜プロジェクト名＞",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
+    "start": "node server.js"
  },
```

# アプリを起動する
ルートディレクトリで次のコマンドを実行し、アプリを起動します。

```
$ npm run build
$ node server.js
```

http\://localhost:5000でアプリにアクセスすると、ページをリロードしても404が返却されない、かつハッシュ記号もurlから削除されているはずです。

参考：
[Vue.jsで作ったアプリをHerokuにデプロイ](https://qiita.com/kottyan/items/dbc1edb82e8562235fac)
[vue-routerのルーティングURLからハッシュを除去しつつ、URL直接指定でも表示させる（Node, Express）](https://qiita.com/uegaki-masaaki/items/3766c7b3fb106e36f5df)
【初心者でもわかる】同じ属性値（nameやvalue）を持つチェックボックスも連動してチェックさせたり外したりする方法

# どうも7noteです。jQueryで同じ属性値同士を連動させる方法について。

どうも7noteです。
この記事は以下へ引っ越しました。

https://naruweb.com/coding/form-interlocking/
Laravelのキャッシュクリアの備忘録

上5つしかしてなかったので備忘録

```bash
php artisan cache:clear &&
php artisan config:clear &&
php artisan config:cache &&
php artisan route:clear &&
php artisan view:clear &&
php artisan clear-compiled &&
php artisan optimize &&
composer dump-autoload &&
rm -f bootstrap/cache/config.php
```

参考
https://qiita.com/A-Kira/items/5fd039217ba992481267
【Qiita】Qiitaにスマホから新規投稿する方法

# 概要
スマートフォンからQiitaにアクセスした場合、リンク経由で新規投稿画面に辿り着けない（多分）ため解決手法を記載します。

* 下図の通り、新規投稿画面へのリンクなどは見当たらない。（デスクトップモードでも同様）
![8C454D6D-65BD-4F79-ACF8-515E3AD29192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670024/b5724f00-c9ed-d712-c4de-c6cb9d1f755c.png)

# 再現環境
* iPhoneXR/iOS14/Safari
* SOV42(Xperia8)/Android10/Chrome

# 結論
下記URLに直接アクセスすることで新規投稿画面が開きます。

```html:URL
https://qiita.com/drafts/new
```
* 新規投稿画面。
![3B6C0F25-E0EA-4F6E-879C-E76CFCCE6E51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670024/bd2ede78-2c67-9812-b458-4a72c1540a4d.png)


* 一旦保存すれば、下書き画面から参照・編集・投稿が可能であることを確認できた。
![990B13F3-8BE7-4E4E-828E-EDDAB8B2E453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670024/39c88996-701c-57d5-a777-05d9e13328b6.png)


# 補足
2020/10/13現在。Qiitaの仕様変更などによって状況は変わる可能性があります。
キーワードで勉強しよう！ - Typescript

##Typescript
既存のJavaScriptではできなかった型定義やクラス生成などを可能にしたスーパーセット（上方互換）言語

##JavaScripとTypeScript、何が違う？
※基本、TypeScriptはJavaScriptの拡張言語のため、JavaScriptでできる機能は全部使える。
・型定義が可能

```javascript:JavaScript
var name = 'kim';
```

```typescript:TypeScript
var name: string = 'kim';
```

・インターフェース、クラスがつかえる

```typescript:TypeScript
class Person{
    name: string;
    age: number;
}
```

・外部ライブラリで定義されている型を使用可能
・ジェネリックが使える

```typescript:TypeScript
function getType<T>(arg: T): T {
  return arg;
}

getType<number>(1); // 1
getType<string>('文字列'); // 文字列
```

##型定義が可能になって利点は？
予見できなかったエラーに対応しやすいし、コンパイルする前に型関連エラーを解消することができる

```javascript:JavaScript
var num1 = 1;
var num2 = '2';

console.log(num1 + num2) // 3
```

```typescript:TypeScript
var num1: number = 1;
var num2: string = '2';

console.log(num1 + num2) // エラー発生
```

##参考
[参考１](https://qiita.com/EBIHARA_kenji/items/4de2a1ee6e2a541246f6#typescript%E3%81%A8%E3%81%AF)
[参考２](https://www.sejuku.net/blog/93230)
Ubuntu 20.04 Chromeキャッシュをtmpfsに置いて使う備忘

Ubuntu 20.04 Chromeキャッシュをtmpfsに置いて使う備忘です。主に自分用です。意外にすっきりまとまって書かれた最新情報がないのでお役に立てば。

##OS
~~~
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
(略)
~~~

##Chrome
~~~
$ sudo apt list --installed | grep chrome
google-chrome-stable/stable,now 86.0.4240.75-1 amd64 [installed]
~~~

##fstab
~~~
$ sudo cat /etc/fstab
tmpfs /var/tmp/ramdisk tmpfs defaults,noatime,size=4096m 0 0
tmpfs /home/dk4130523/.cache/google-chrome tmpfs defaults,size=1024m,noatime,mode=0777,uid=1001,gid=1001 0 0
~~~
ユーザー名は読み替え、書き換えを行ってください。また、メモリ32GB搭載のうち4GBをtmpfs(ramdisk)に割り当てています。ここも使用環境に応じて適宜変えてください。

##rc.local
~~~
$ sudo cat /etc/rc.local
/usr/bin/mkdir -p /var/tmp/ramdisk
~~~

##rc.local動作設定
以下などを参考に。

- https://synaptica.info/2020/06/26/ubuntu-20-04-rc-local-start-a-process-after-boot/

##起動オプションなど
僕の場合はlxdeでalacarteを使い以下を設定、使用しています。

~~~
/usr/bin/google-chrome-stable --proxy-server="ip-address:port-number" --renderer-process-limit=1 --disk-cache-size=402653184 --media-cache-size=402653184 %U
~~~

上のfstab設定1024MBに対し、402653184 bytes /1024 /1024 = 384MBを、ディスクキャッシュとメディアキャッシュ各々に割り振っています(すなわち合計768MBが上限)。現在の僕の使い方では到底ここまで達しません。

~~~
$ df -lha | grep tmpfs
(略)
tmpfs           1.0G  247M  778M  25% /home/dk4130523/.cache/google-chrome
tmpfs           4.0G  364K  4.0G   1% /var/tmp/ramdisk
(略)
~~~

動作は非常に軽快です。以上です。
DataGrip localhost環境接続できない...それはESETかも。

local環境にあるDockerのPostgresにDataGripから接続しようとして発生した。
必要な情報を入力して`Test Connection`をクリックすると...

`LocalDataSource@72fe1880: postgres@localhost (PostgreSQL): process exited.`

は？！どういうこと？？
なにか指定が間違えている？？
環境、または使用しているDriverやバージョンが古いとか？

試しに適当なSQLiteに接続を試みるが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91442/1886bab8-5428-ea47-95bb-5e691f1b362e.png)

`LocalDataSource@64aa21e3: mytest.sqlite3 (SQLite): process exited.`

え、また？！
これに繋がらないって、どういう状況？

## 結論

こうするとうまくいく。

![eset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91442/27fee47c-2cd5-7bcc-d3d3-a524ad6e1491.png)


セキュリティーソフトはデフォルト（または推奨されている方法）で利用したい、
と思っているので極力設定はいじらずで使っていますが、これちょいちょい引っかかるな。

という話でした。
ご参考になれば！
【rails】requireメソッドとpermitメソッド

requireメソッドとpermitメソッドについて学習したため、アウトプットいたします。

この記事を読むと、require,permitメソッドの意味と使い方を理解できます。


#requireメソッドとは？
ストロングパラメーターのメソッドの1つで、paramsからとってくるデータのオブジェクト名を指定する。
※ストロングパラメーターについてわからない場合は、Googleで検索してみてください。


```csharp:使い方例

def user_params
 params.require(:user)
end
```

これによってユーザーというオブジェクトのデータを指定しています。

#permitメソッドとは？
ストロングパラメーターの1つで、paramsから取ってくるデータのキーを指定する。



```csharp:使い方例


def
tweet_params
params_permit(:name, :text, :image)
end
```

つまり2つの違いはキーを指定するかオブジェクトを指定するか。

そのため、permitメソッドと、requireメソッドを同時に使うこともある。



```csharp:例

def user_params
 params.require(:user).permit(:name, :email, :password)
end
```

userオブジェクトを指定し、さらにuserオブジェクトのなかに定義されたname,email,passwordのキーを指定している。
Unalignable boolean Series provided as indexerとなったときの対応方法

# 事象 : `notna`でNaNではないインデックスでデータを抽出しようとしたら怒られた
- 環境
    - macOS Catalina バージョン10.15.7
    - Python 3.8.5
    - pandas 1.1.3

```py
import pandas

if __name__ == '__main__':
    df = pandas.read_csv('CSV.csv')
    print(df[df.query('名前 == "ぽんすけ"')['開始'].notna()])
```

```bash:エラーメッセージ
pandas.core.indexing.IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).
```

## 原因 : 不明
抽出しようとしているDataFrameのインデックス分のインデックスが`notna`の結果にないから？
誰か教えて欲しい。

```py
# 抽出しようとしているDataFrameのインデックスは0~39までの40ある
print(df)
#       名前  回数     開始     終了
# 0   ぽんすけ   1   9:00  18:00
# ...省略...
# 39  ぽんすけ  10    NaN    NaN

# notnaの結果のインデックスは抜け番がいっぱいで10しかない
print(df.query('名前 == "ぽんすけ"')['開始'].notna())
# 0      True
# 2      True
# 5      True
# 11     True
# 14    False
# 21     True
# 24     True
# 29    False
# 34     True
# 39    False
# Name: 開始, dtype: bool
```

`notna`の結果のインデックスに合うDataFrameから抽出すればなんとかなりそう

```py
# notnaの結果のインデックスに合うDataFrame
print(df.query('名前 == "ぽんすけ"'))
#       名前  回数     開始     終了
# 0   ぽんすけ   1   9:00  18:00
# 2   ぽんすけ   3   9:00  13:00
# 5   ぽんすけ   7  12:00    NaN
# 11  ぽんすけ   5   9:00    NaN
# 14  ぽんすけ   4    NaN    NaN
# 21  ぽんすけ   2  18:00    NaN
# 24  ぽんすけ   6  18:00    NaN
# 29  ぽんすけ   9    NaN  18:00
# 34  ぽんすけ   8  12:00    NaN
# 39  ぽんすけ  10    NaN    NaN
```

### 対応 : notnaの結果のインデックスに合うDataFrameから抽出する
```py
import pandas

if __name__ == '__main__':
    df = pandas.read_csv('CSV.csv')
    ponsuke = df.query('名前 == "ぽんすけ"')
    print(ponsuke[ponsuke['開始'].notna()])
```

```bash:できた
      名前  回数     開始     終了
0   ぽんすけ   1   9:00  18:00
2   ぽんすけ   3   9:00  13:00
5   ぽんすけ   7  12:00    NaN
11  ぽんすけ   5   9:00    NaN
21  ぽんすけ   2  18:00    NaN
24  ぽんすけ   6  18:00    NaN
34  ぽんすけ   8  12:00    NaN
```
ActiveRecordでカラム名のメソッドをオーバーライドしたときに、カラムを参照する方法

## 背景
モデルにDBのカラム名と同名のインスタンスメソッドを定義し、さらにそのメソッド内でカラムを参照したい

## 方法
２つ方法がある模様

```ruby
class Person < ApplicationRecord
  def name
    self[:name]
  end

  def name
    read_attribute(:name)
  end
end
```

[The Rails Style Guide](https://github.com/satour/rails-style-guide/blob/master/README-jaJA.md#read-attribute) では、`self[:name]`のほうをお勧めしている

## 参考
https://github.com/satour/rails-style-guide/blob/master/README-jaJA.md#read-attribute
https://stackoverrun.com/ja/q/5968719
Dockerでのエラー解消に繋がったコマンド

# はじめに
Docker環境構築において、役に立ったコマンドを備忘録として残します。
作成したものの、エラーが解決出来なかったときにおすすめです。

# コンテナの停止、削除
## コンテナの停止

```:コンテナ確認
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
797b4265f3d2        try_web             "/bin/sh -c 'rm -f t…"   24 minutes ago      Up 23 minutes       0.0.0.0:3000->3000/tcp              try_web_1
```
CONTAINER IDを指定します。

```:コンテナ停止
$ sudo docker stop 797b4265f3d2
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
```

## コンテナの削除
あくまで停止しただけなので、削除も行います。

```:コンテナ確認
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
797b4265f3d2        try_web             "/bin/sh -c 'rm -f t…"   24 minutes ago      Up 23 minutes       0.0.0.0:3000->3000/tcp              try_web_1
```
CONTAINER IDを指定します。

```:コンテナ削除
$ sudo docker rm 797b4265f3d2
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
```

# imageの削除
コンテナは削除しましたが、imageは残っています。

```:imageの確認
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
try_web             latest              c0ee642ca6bd        About an hour ago   1.01GB
```
IMAGE IDを指定します。

```:imageの削除
$ sudo docker rmi c0ee642ca6bd
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
```

# docker-compose exec app rails db:createのエラー
私の場合ですが、Access denied for user のエラーが出ていたため、
mysqlを確認しました。
```#``` の後にmysql -u root -pと記述し、mysqlにログインします。

```:ターミナル
$ docker-compose up -d
$ docker-compose exec db bash
root@e5504121a08b:/# mysql -u root -p
```
終了する場合はexitと記述してください。

ここでパスワードが間違っていたため、
docker-compose exec app rails db:create
のエラーが出ていました。

# まとめ
あくまでも一例のため、まだまだ便利なコマンドはあると思います。
私と同じ状況になった方の助けになれば幸いです。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork
VPCSC で GCSにIP制限かけて Service Transfer Service を実行すると Request is prohibited by organization's policy. エラー

# 背景
あるプロジェクトをVPCSCでGCSにIP制限をかけた。
そのGCSでService Transfer Service (S3 -> GCS)を実行しようとしたら以下のエラーがでた。

```
VPC Service Controls
Cloud Storage
testIamPermissions
project-xxxx@storage-transfer-service.iam.gserviceaccount.com
Request is prohibited by organization's policy. vpcServiceControlsUniqueIdentifier: xxx
```

監査ログでは以下のようなログ

```
requestMetadata: {
   callerIp: "private"    
   destinationAttributes: {
   }
   requestAttributes: {
   }
  }
  resourceName: "projects/xxx"   
  serviceName: "storage.googleapis.com" 
```

# 解決方法

Access Context Managerに `project-${project_number}@storage-transfer-service.iam.gserviceaccount.com ` のアカウントを追加したら動いた。

自分のプロジェクトでは、Access Context Managerはyaml管理されているのでyamlに上記アカウント追加して access context manager の updateコマンドを実行した。

```sh
gcloud access-context-manager levels update accessPolicies/xxx/accessLevels/gdp --basic-level-spec=sample.yaml --combine-function=or
```

```yaml:sample.yaml

- ipSubnetworks:
  - xxx.xxx.xxx.xxx/32
  - xxx.xxx.xxx.xxx/32
- members:
  - project-${project_number}@storage-transfer-service.iam.gserviceaccount.com
```

# 参考

#### [Storage Transfer Service を VPC Service Controls とともに使用する](https://cloud.google.com/storage-transfer/docs/transfer-with-vpc-sc?hl=ja)

#### [Access Context Manager_アクセスレベルの作成](https://cloud.google.com/access-context-manager/docs/create-access-level?hl=ja#gcloud_3)

#### [アクセスレベルの YAML の例](https://cloud.google.com/access-context-manager/docs/example-yaml-file?hl=ja)

#### [gcloud access-context-manager levels update](https://cloud.google.com/sdk/gcloud/reference/access-context-manager/levels/update?hl=ja)
【AWS初学者用】AWS セキュリティグループとネットワークACLの違い

# 本記事について
本記事はAWS初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## セキュリティグループ
セキュリティグループとはEC2インスタンスなどに適用することができるファイアウォール機能です。
EC2インスタンスから出る通信(往路)を**アウトバウンド**、EC2インスタンスに入る通信(復路)を**インバウンド**と呼びます。
セキュリティグループのデフォルトの設定値はアウトバウンドは全て許可、インバウンドは全て拒否になっています。「去るもの追わず、来るもの拒む」という状態です！付け入る隙がないですね...
そしてセキュリティグループはインスタンスに対し複数適用する事が可能で、**ステートフル**な制御をします。
(※ステートフルについては私自身こんがらがってしまったので後ほど図で解説します。)

## ネットワークACL
ネットワークACLはサブネットに適用する事ができるファイアウォール機能です。
セキュリティグループと同じ様にアウトバウンド通信・インバウンド通信にルールを適用します。ネットワークACLは主にサブネット間の通信の制御に用いられます。
セキュリティグループとの違いとして**「1つのサブネットに1つのネットワークスACLを設定可能」**、**「デフォルトの設定値は全て許可」**、「ステートレスな制御」が挙げられます。

## 「ステートフル」と「ステートレス」
ステーツフルとステートレスの違いはどの視点から見るかによって変わってるらしく、私も調べてみましたが決定的な記事が見つけられなかったです。
まあしかし、どの様な動きをするのか分かっていれば言葉の意味などはさほど問題ない！と言い聞かせました...
とりあえず自分がわかりやすい様に図にしてみました。
![セキュリティグループとネットワークACL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/782134/ec709e15-9f4b-4076-9574-afc1df095ad9.png)

緑の枠がネットワークACLで、赤の枠がセキュリティグループです。
緑の丸はネットワークACLでの制御が適用された事を表し、赤い丸はセキュリティグループでの制御が適用されたことを表しています。

この図でわかることは往路でセキュリティグループの制御が適用されたら、復路では制御にかかわらず通信は許可されています。
逆にネットワークACLでは往路と復路両方に制御が適用されています。

これらをまとめると往路と復路で制御のルールが同じ(往路が許可されたら復路も許可！)なのが**ステートフル**！
往路と復路で制御のルールを変える事ができるのが**ステートレス**！

とは言ってもこれは私なりの解釈なので気になる方は自分で調べてみてください。



| 項目                  | セキュリティグループ     | ネットワークACL                    |
| -------------------- |            ------   | ------------------------------ |
| **選択範囲**　         | インスタンス           | サブネット　                      |
| **デフォルト設定**       | IN : 拒否  OUT : 許可| 全て許可                        |
| **ステータス**　　　　   | ステートフル           | ステートレス　　　　　　　　　　　　　 |




## まとめ
それぞれの違いはいくつかありましたが大きな違いとしてはステートフルとステートレスの部分とインスタンスに適用かサブネットに適用かなのではないでしょうか？
もっとわかりやすい説明があったらぜひとも教えて頂きたいです...
AWS LambdaでSlackに添付ファイルとして投稿(Python)

Amazon S3からファイルを取得してSlackに添付ファイルとして投稿するAWS Lambdaを作っていたが、AWS LambdaのPython環境にはrequestsモジュールが入っていなかったので苦戦した。

## 前提・環境
AWS Lambda Python環境

## やりたかった事
1. Amazon S3からファイルを取得する
2. ファイルをSlackの`files.upload` APIで添付ファイルとして投稿する(content typeはmultipart/form-dataを使う)

## できなかったこととその理由
Pythonでのファイルのアップロードは、
https://qiita.com/5zm/items/92cde9e043813e02eb68
や
https://www.it-swarm-ja.tech/ja/python/python%E3%81%A7%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A8-multipart-formdata%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%EF%BC%9F/1069592211/
にあるように、requestsを使うのが定番。
しかしAWS LambdaのPython環境にはrequestsモジュールが入っていなかった。

## 解決方法
- requestsの含まれるLambda Layerを使う
- **requestsではなくurllib.requestを使う <- 採用**

## 実装
urllib.requestを使うと言ってもmultipart form dataを作成する必要があるので以下のURLを参考にした。
https://necoyama3.hatenablog.com/entry/20150608/1434982490
この記事内に記載にある`encode_multipart_formdata`メソッドはデータ部とファイル部をmultipart form dataの形式に変換してくれる。

これを利用して以下のようにした。

```python:
## ポイント1: fileパラメータを除いたパラメータを定義する
data = {
   'token': <your token>,
   'channels': <your channels>,
   'initial_comment': key + 'を投稿します:eyes:',
   'filename': key,
   'filetype': 'webp'
}

url = "https://slack.com/api/files.upload"
content = open('/tmp/' + key, 'rb').read()

## ポイント2: fileパラメータを定義する
file = {'file': {'filename': key, 'content': content}}

## ポイント3: dataとfileをひとつのmultipart form dataに変換する
content_type, body = encode_multipart_formdata(data, file)

header = {'Content-Type': content_type}
request = urllib.request.Request(url, body, header)
response = urllib.request.urlopen(request)
```

ポイントになるのは
1. `data`変数でSlack files.upload APIのfileパラメータを除いたパラメータを定義する
2. `file`変数でSlack files.upload APIのfileパラメータを定義する
3. `encode_multipart_formdata`メソッドでmultipart form dataに変換する

の3点。
これでrequestsを使わずにAWS LambdaでSlackにファイルを投稿できるようになった。

## 最後に
Lambda Layerを作るのとどちらが楽なんだろうか…？
ngraphで作成するグラフのサイズについてメモ

# パラメーターをまとめる

ngraph-gtk (ngraph) で作成するグラフの大きさや縦横比は、そのグラフを描画する用紙（ページ）の設定と、グラフの新規作成時に与えるパラメータで決まります。基本的に ngraph のグラフは、A4縦(Portrait)の用紙、210[mm]×297[mm] に、140[mm]四方で描画することがデフォルトになっているので、グラフの縦横比を変化させたいのであれば、最初にサイズを与える必要があります。

いくつか使えそうな比率と、それに合わせたパラメーターを計算したのが下記の表です。「グラフ→ページの設定」でA4P(縦)かA4L(横)を設定してから、「グラフ→新規作成」で描画したいグラフのタイプを選んで、パラメーターを設定します。

|A4P| デフォルト(1:1) | 4:3| 白銀比(1.414:1) | 黄金比(1.618:1) | 16:9 
|:-:|:-:|:-:|:-:|:-:|:-:|
| X      | 35  | 35  | 35  |35  | 35  |
| Y      | 220 | 202| 198 | 192  | 190  |
| 幅(W)  | 140 | 140 | 140 | 140 | 140 |
| 高(H)  | 140 | 105| 98  | 86  | 80  |

|A4L| デフォルト(1:1) | 4:3| 白銀比(1.414:1) | 黄金比(1.618:1) | 16:9 
|:-:|:-:|:-:|:-:|:-:|:-:|
| X      | 79 | 55  | 49  |35  | 24  |
| Y      | 175 | 175 | 175 | 175 | 175 |
| 幅(W)  | 140 | 188 | 200 | 228 | 250 |
| 高(H)  | 140 | 140 | 140 | 140 | 140 |

なお、A4紙自体は白銀比です。

# 以下、計算方法

フレーム/方眼グラフを作成する場合、デフォルトではグラフの幅と高さを140mm四方としています。
紙の縦方向py軸は、原点(px,py)=(0[mm],0[mm])を紙の左上として、下方向が正です。一方、グラフの縦方向y軸は、上記の紙座標で定めた点を原点として、上方向が正になります。
紙の横方向px軸と、グラフの横方向x軸は、両方とも右方向が正になります。

以上から、
グラフのX方向の始点は (210［mm］-140［mm］)/2 ＝ 35［mm］
グラフのY方向の始点は (297［mm］-140［mm］)/2 + 140［mm］ ≒ 220［mm］
(切り上げて最も近い偶数にした)
という計算になります。実際、用紙A4縦のフレーム、方眼グラフのデフォルト値は
X 35.00［mm］
Y 220.00［mm］
幅(W) 140.00［mm］
高(H) 140.00［mm］
となっています。

一方、例えば gnuplot の場合、縦横比のデフォルト値は terminal によって変わります。

https://github.com/gnuplot/gnuplot/blob/master/term/post.trm

```
" The default size for postscript output is 10 inches x 7 inches. The default",\
" for eps output is 5 x 3.5 inches.  "
```

https://github.com/gnuplot/gnuplot/blob/master/term/cairo.trm

```
#define CAIROEPS_PARAMS_DEFAULT { \
    CAIROTERM_EPS, INCHES, FALSE, FALSE, 
    1.0, {1.,1.,1.}, FALSE, FALSE, TRUE, FALSE, NULL, \
    12, 0.5, 5*72., 3*72., 0.25, 1.0, 1.0, FALSE \
}
```
postscript系は 10:7 で白銀比(1.414:1 ≒ 10:7.1) に近く、cairo系(epscairo, pdfcairoなど) は 10:6 で黄金比 (1.618:1 ≒ 10:6.2 ) に近い設定です。

というわけで、これらの比率を考慮したグラフをngraphで描画するには、ちょっとした計算が必要になるので、まとめてみた次第です。16:9は細長すぎるので省いてもよかったかもしれません。

グラフの片方の辺を140[mm]に固定したのは 1:1 のデフォルトに合わせた（A4の短辺 210[mm] 側が 140[mm] になるようにしている）からなので、これをもう少し拡大もしくは縮小する必要がある場合、計算をやりなおす必要があります。
Vue.Draggableのtagの挙動がよくわからないのでちょっとゴリ押しした

#環境

nuxt :2.13.3
vue.js : 2.6.11 
Vuetify : 2.3.4
Vue.Draggable : 2.24.0

nuxtのモード
▸ Rendering:   server-side 
▸ Target:      server
#実現したいこと
Vuetifyのv-cardコンポーネントをVueDraggableで並べ変えたかった。


#ぶち当たった問題
このコンポーネントを



```
<template>
  <v-layout>
    <v-container>
      <draggable tag="v-row">
        <v-col v-for="i in 10" :key="i" cols="3" class="ma-0">
          <v-card>
            <v-card-title>
              {{ i }}
            </v-card-title>
          </v-card>
        </v-col>
      </draggable>
    </v-container>
  </v-layout>
</template>
<script>
import draggable from 'vuedraggable'
export default {
  components: {
    draggable
  }
}
</script>


```


```
yarn dev
```
して表示したとき
(以後開発モード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402287/964a9542-766d-ebb8-9329-dfaf1ac37c75.png)



```
yarn build
yarn start
```
して表示したとき(以後ビルドモード)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402287/3f3c2c1f-587e-b510-8e66-bcf3c16714ec.png)

とで表示が違う。

#もっと詳しく
ChromeのDevToolsのElementsを見てみると

[開発モード]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402287/878c6c02-4339-cae1-bc4f-05c373f2bdb7.png)


[ビルドモード]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402287/75b18e25-55ac-8254-0c16-29e63eece192.png)

開発モードではv-rowコンポーネントが```<div class="row">```になっているが
ビルドモードではただのv-rowタグになっている

#VueDraggableのtag Propsとはなにか

tagにコンポーネントやHTMLタグを指定することによって```<draggable>```のをそのタグやコンポーネントに置き換えてくれるもの（だと解釈してる）
標準では```<div>```になる

``` tag="v-row" ```とすることで、Vuetifyのv-rowコンポーネントを指定しているはずだが、ビルドモードではなぜか反映されない。
参考
>[https://github.com/SortableJS/Vue.Draggable](https://github.com/SortableJS/Vue.Draggable)

#自分なりの解決策
表示したいhtmlは```<div class"row">```なので
```<draggable tag="v-row">```を```<draggable class="v-row">```
に変更した。
これによって開発モードと同じ表示にすることが出来た。


**この解決方法ではゴリ押しすぎる。なんか他にいい方法がアリそう……**
フルスタックエンジニアとは

#プログラミング勉強日記
2020年10月13日
今日は授業の課題や発表などに追われているので、日曜日に参加したイベントで聞いた「フルスタックエンジニア」とはなにか簡単にまとめようと思う。

#フルスタックエンジニアとは
　ネットでフルスタックエンジニアについて調べてみると以下のようなことが書いてあった。

> フルスタックエンジニアとは、システム開発やウェブ開発などのエンジニアリング業務において設計から開発・運用まで全ての行程を手掛けることができるエンジニアを指します。

　なんでもできる万能なスキルを持っているフルスタックエンジニアってとってもかっこいい！って思ったけど、フルスタックエンジニアを目指すのは簡単ではなさそう。

#強みと特徴

- 人件費削減になる
- 開発スピードの向上
- スタートアップから重宝される

　以上の点は説明しなくてもなんとなく理解できると思う。人件費の削減や開発スピードが上がるといったメリットがある。
　フルスタックエンジニアの必要性や求められる背景としては、ITエンジニアの役割の変化と海外開発やクラウドサービスの登場、技術が一般的になったことなどが挙げられる。

#これからのフルスタックエンジニア

　「今まではコードが書ける人がフルスタックエンジニアと思われていたが、実際コードはGoogleで調べればすぐに出てくる。なので、これからの時代は言語選定から決められた期間でコストをかけずにユーザからの悪い評価を良い評価に変えられるそんなエンジニアがフルスタックエンジニアだ。」というお話を日曜日のイベントでお伺いした。

#感想
　私の目指すIT企業は変化が激しいので、時代の流れを乗るではなく作っていけるようなエンジニアになりたいと思った。世界レベルで、最新の技術を知り、扱える人になりたいと思う。そのために勉強を重ねていこうと思う。

#参考文献
[フルスタックエンジニアとは？仕事内容・スキル・年収・将来性
](https://www.bigdata-navi.com/aidrops/3126/#:~:text=%E3%83%95%E3%83%AB%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E9%96%8B%E7%99%BA%E3%82%84%E3%82%A6%E3%82%A7%E3%83%96%E9%96%8B%E7%99%BA,%E3%81%A8%E5%91%BC%E3%81%B0%E3%82%8C%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)
[フルスタックエンジニアとは？年収と最低限必要な3つのスキル](https://itpropartners.com/blog/7311/)
paralleldots APIをnode経由で使用してみた [感情分析編]

# はじめに
paralleldots AI APIというテキストから感情を分析するAPIがあるので、Nodeをプロキシとして利用し、このAPIを使ってみました。

[paralleldots](https://www.paralleldots.com/)


## 環境
・ node version : v12.18.3
・ npm version : 6.14.6

### URIと機能
|Path |HTTPメソッド  |機能  |
|---|---|---|
|/api/v1/emotion |POST |入力テキストの全体的な感情と各感情ラベル（Happy、Sad、Angry、Excited、Bored、Fear）の信頼スコアを含むjson応答を返します。  |

### 使用したparalleldots AI API

**paralleldots AI APIとは？？**
開発者向けの包括的なドキュメント分類およびAPIのセットです。10億を超えるドキュメントでトレーニングされており、感情分析や感情検出などを提供しているそう。

今回は、paralleldots AI APIの[**/v4/emotion**]こちらを使用していきます。

#### 設定できるパラメータ
|名前|詳細 | Required | Type  |
|---|---|---|---|
| text |分析したい文章を入力します。| Yes  | string/array|
| api_key | Api key | Yes  |string|
| lang_code |言語コード| Yes |string|

**・ ただ、今回は、nodeでプロキシしているので、プロキシサーバ側で[api_key]及び[lang_code]は設定しています。**

### 構成

```package.json
{
  "name": "node_poc",
  "version": "1.0.0",
  "description": "paralleldots AI API",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.20.0",
    "express": "^4.17.1"
  }
}

```

```app.js
const express = require("express");
const app = express();
const axios = require('axios');

const server = app.listen(9000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

app.post("/api/v1/emotion", function(req, res, next){

    let params = new URLSearchParams();
    params.append("api_key", '××××××××××××××××××××××××××××');
    params.append("lang_code", 'en');
    params.append("text", req.query.text);

    try {
         axios.post('https://apis.paralleldots.com/v4/emotion', params)
        .then((response) => {
            res.send(response.data)
        })
    } catch (error) {
      console.error(error);
    }
});


```


### Response
今回は、requestを日本語で行おうと思ったのですが、[**lang_code**]を英語以外を使用したい場合は、無料枠では使用できない為、仕方なく英語で行いました。

textには、
**Be careful about reading health books. You may die of a misprint.**
日本語訳にすると、[**健康系の本を読むときは注意しなさい。ミスプリントのせいであなたは死ぬかもしれない。**]
という意味です。笑

Requestは、Postmanを使用しました。(curlより見やすい為)

![スクリーンショット 2020-10-13 19.30.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/44840fc1-98ad-caca-a419-a3a728ae23cf.png)


・ 実際のResponse

```
{
    "emotion": {
        "Happy": 0.0872024649,
        "Angry": 0.2344884125,
        "Bored": 0.0416403769,
        "Fear": 0.3095755387,
        "Sad": 0.1825278824,
        "Excited": 0.1445653247
    }
}
```


### 結果

![chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/14b0fe41-7074-f8b2-8a65-ea634303eea8.png)

やはり、死ぬかもしれないという恐怖を入れ込んだ文章を送ったため、Fearが一番結果の数値として高いことが分かります。
精度的にどうなのかは、個人の感性に依存しそうですが、、


# 参照
・ [paralleldotsのドキュメント](https://apis.paralleldots.com/text_docs/index.html?shell#introduction)
azure VMでsudoersファイルのsyntaxエラーを起こしちゃったときの対処法

## ある時、Azure VMで`sudo ls`したら`sudo: parse error`エラーが
どうやら/etc/sudoers.d/user(sudoersファイル)の修正ミスでsyntax errorとなっていてsudoできなくなっていました・・・

## 対処法
```powershell
# ブラウザからログイン
az login

az vm run-command invoke -g [リソースグループ名] -n [VM名] --command-id RunShellScript --scripts "rm -rf /etc/sudoers.d/user"
```

あとは必要に応じておかしくなる前の `/etc/sudoers.d/user`を復元してください。
sudoersファイルを編集できる権限が消えちゃったときは`VMコンソール` - `パスワードのリセット`から復旧用のユーザを作成して作業すると良さそうです。

## 感想
とっても簡単でビックリ。
AWSで同じ問題が発生した際（どちらも私がやったんじゃないよ・・・）はdiskを別のVMにマウントしなおしてゴニョゴニョしたんですが、Azureはそれよりもさらに簡単に対応できました。
Bootstrapに飽きてきたら React を勉強するタイミングかもしれない件

# なぜこの記事を書こうと思ったのか
私も含めた Rails 初心者の皆さまはきっと [Bootstrap](https://getbootstrap.com/) を使ったことがあるはずです。

- Railsチュートリアルで
- ポートフォリオで
- 入社してからの新人研修で
- 個人開発で

ここで皆さんに問いたい。

**Bootstrap飽きません？**

はい、流石に飽きました。使いすぎです。それだけ人気だということですが、もう少しリッチな UI を実現したい。

だけど正直 **Bootstrap臭** を排除したいだけで、 CSS をゴリゴリ書いていきたいわけではない。楽したい。しかもカッコよくしたい。

決まりです。
React を勉強しましょう。
React を勉強すると [Material UI](https://material-ui.com/) という最強のデザインフレームワークが使えるようになります。

# Material UI って？
https://material.io/design

ざっくり言うと Google が提唱している効果的なデザインのパターンや法則のこと。
それをライブラリとして簡単に自分のアプリケーションに取り入れられるようにしてくれているのが Material UI というライブラリなのです🙌

# どんなデザインが導入できるの？
ボタン、入力フォーム、カード、アイコンなどありとあらゆるデザインが１つ１つコンポーネント（部品）として提供されています。
あまりにも多くて全てを紹介することはできませんが、興味を持って頂くのが目的です。


以下サンプルは全て公式サイトにあるものを使わせて頂きます。
https://material-ui.com/

[サインアップ画面のテンプレート](https://material-ui.com/getting-started/templates/sign-in/)
![Screen Shot 2020-10-11 at 17.20.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425320/04c39f59-04f8-5c55-73bc-bd6089ebc27b.png)


このようにシンプルで洗練されたデザインが魅力です。幅広い人に好印象を持たせられるテイストなのではないでしょうか？

今までBootstrap臭が漂っていたあなたのアプリケーションが一気にモダンな印象になります。すごい！！

Google の提供している各種サービスも基本的には Material design を採用しているはずなので、 **Google っぽい** デザインと言えば良いでしょうか。

# おわりに
もちろん無料で使えますし、導入も npm パッケージを使って、

```
$ npm install @material-ui/core
```

を実行するだけです。

私は最近React の勉強を始めました。
始めた理由は、「そろそろフロントもやっておかないとな〜」というのもありますが、この **Materil UI を使いたくなったから** というのが大きいです。

デザインがイケてるとやっぱり開発のモチベーションが上がります。
もうBootstrapを卒業したいという方は是非React を勉強して Material UI を使ってみてはいかがでしょうか？
terragrunt(xxx-all系)でtfnotifyを使う方法

[[terragrunt] xxx-all系で個別処理にパイプやリダイレクト等の処理を追加する方法](https://qiita.com/hiko1129/items/9df1b50bbac087e25de5)のパイプで出力を渡す先をtfnotifyに変更するだけ。

具体的には下記のような感じのscriptを用意して、

＊ 下記のような作りなら、ディレクトリ移動(terragrunt plan-all等が行ってくれていること)をterragrunt側に依存しておくことで、terragrunt moduleへの対応を自分で書かずに済む。

```shell:/usr/scr/app/script/tfwrapper.sh
#!/bin/bash

set -eu

terraform "$@" 2>&1 | tee ./terraform.log

type=$(echo "$@" |  awk '{print $1}')

if [ "$type" != "plan" ] && [ "$type" != "apply" ]; then
  exit 0
fi

current_directory=$(pwd)

tfnotify --config "$TF_NOTIFY_FILE_PATH" "$type" --message "$TF_VAR_env $current_directory" < ./terraform.log
```

下記のように呼び出す

```
$ terragrunt plan-all --terragrunt-non-interactive --terragrunt-tfpath /usr/src/app/script/tfwrapper.sh
```

プロジェクトルート以外で、terragrunt.hclが存在しているディレクトリ内で個別に`terragrunt plan`や`terragrunt apply`を実行すると依存順序（terragrunt.hclで定義したdependencies）が解決されないので、tfnotifyをそのまま使いたければ現状上記方法で解決するしかないと思います。
Android Studio 4.1に上げたらParameter 'directory' is not a directoryでBuildできない

pluginのアップデートがあるよ〜って出たのでアップデートしたらエミュレータへのinstallに失敗するようになって、試行錯誤ののち4.1以上じゃないと使えないplugin入れちゃったみたいで、勢いでAndroid Studioも4.1にしたら、

> Execution failed for task ':app:dataBindingGenBaseClassesHogeDebug'.
> Parameter 'directory' is not a directory: /Users/ibuse/Documents/workspace/Fuga/app/build/intermediates/data_binding_dependency_artifacts/hogeDebug

ですって。
cleanしてrebuildしても変化なし
Invalidate Caches/Restart...効果なし

![スクリーンショット 2020-10-13 18.49.46（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537760/639b8233-b0cb-347d-699d-f2b859fcbeae.png)
確かにそんなディレクトリは存在しないので、強引にディレクトリを作ってあげたら
> BUILD SUCCESSFUL

冴えない解決を見た

(追記:2020/10/19)
Android Studio 4.1と言うよりもgradleの問題だった模様。
再度いろいろ検索を行ったところ、以前もヒットしたここの回答から
https://stackoverflow.com/questions/54018148/java-lang-illegalargumentexception-parameter-directory-is-not-a-directory-in

> 1. Delete the .gradle directory
> 2. Invalidate Caches and restart Android Studio.

こんな記述を見つけて、結論としてはプロジェクト内の.gradleディレクトリを消したところで正常化しました。
Invalidate Caches/Restartは必要なさそう
[terragrunt] xxx-all系で個別処理にパイプやリダイレクト等の処理を追加する方法

## xxx-all系で個別処理に処理を追加する方法
＊ [extra_arguments](https://terragrunt.gruntwork.io/docs/getting-started/quick-start/#keep-your-terraform-cli-arguments-dry)や[hooks](https://terragrunt.gruntwork.io/docs/features/before-and-after-hooks/#before-and-after-hooks)ではできない処理が可能な方法です。


下記のような、xxx-all系で

```
$ terragrunt plan-all
$ terragrunt apply-all
```

下記のように、個別のコマンドにパイプを用いたいとき（パイプでなくても同様）は、

```
$ terragrunt plan | tee ./terraform.log
```

terraformのwrapperを準備し、

```shell:tfwrapper.sh
#!/bin/bash

terraform $@ 2>&1 | tee ./terraform.log
```

terragrunt-tfpathオプションに上記のようなファイルパスを渡すことでできます。

```
$ terragrunt plan-all --terragrunt-tfpath ./tfwrapper.sh
```


## 参考
* [The apply-all and destroy-all commands should save log output to file](https://github.com/gruntwork-io/terragrunt/issues/74#issuecomment-471082576)
* [terragrunt-tfpath option](https://terragrunt.gruntwork.io/docs/reference/cli-options/#terragrunt-tfpath)
ATECC608A-TNGTLS検証(AWS IoT Multi-Account Registration接続テスト)(ATECC608A-TNGTLS AWS IoT connection test by using Multi-Account Registration)

#はじめに#
以前、[NXP SE050検証(AWS IoT Multi-Account Registration接続テスト)](https://qiita.com/kmitsu76/items/b7bb4146117a9a59412e)で実施した内容をMicrochip社のATECC608AのTrust and Goという製品で追試する。

前回整理したように、自分のCAを構築して、それを登録、共通のCAで認証されたデバイスを接続させるJust In Time Registrationよりも簡素化した、Multi-Account-Registrationを利用し、チップメーカーのCAを利用してデバイスを認証させる流れとなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/39c10f31-f85d-7c99-dc1d-b217f60e1b0c.png)

#ATECC608AのTrust and Go#
ATECC608Aは16個のスロットの役割、権限を個別に設定できるConfigを設定し使用できるようになる。
また証明書は定義ファイルを生成し、デバイスとセットで使用する。
しかしこの設定と生成が難解なので、事前に設定されたデバイスとして販売されている。
特にTrust and Goはチップを購入した段階で書き込まれている証明書の台帳が入手できるらしい。

[Microchip Direct](https://www.microchipdirect.com/)でTrust and Goを購入してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/3993dc08-7575-b049-57a5-7e2bdc02928d.png)

3/3に発注して3/20に到着した。小ロットでプログラムしてもらう手間を考えるとこんなものだろう。

このOrder History画面から、"Download Manifest"をクリックすると、jsonのファイルがダウンロードできる。
このJSON のファイルの中にオーダー分の証明書が収まっている形。

#AWS側の準備#

AWS CLIから設定を行っていく。

環境

```
aws --version
aws-cli/2.0.56 Python/3.7.7 Windows/10 exe/AMD64
```

今回の検証を行ったGitレポジトリをクローンする。

```
git clone --recursive https://github.com/kmwebnet/ECC608-TNG-AWS-Connect.git
cd ECC608-TNG-AWS-Connect
```

まず、manifest fileから証明書を抜き出すスクリプトを実行し、certs/フォルダ内にPEMファイルとして保存する。

```
pip install python-jose[cryptography]
manifestdecoder.py --manifest <マニフェストファイル>
```

AWS IoTにデバイス証明書を登録した後に割り当てるポリシーを作成する。

```
aws iot create-policy --policy-name wildcardpolicy --policy-document file://wildcardpolicy
{
    "policyName": "wildcardpolicy",
    "policyArn": "arn:aws:iot:ap-northeast-1:XXXXXXXXXXXX:policy/wildcardpolicy",
    "policyDocument": "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iot:Connect\",\n                \"iot:Publish\",\n                \"iot:Receive\",\n                \"iot:Subscribe\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
    "policyVersionId": "1"
}
```

後はデバイスの数だけ証明書を登録し、ポリシーを割り当てる。

```
aws iot register-certificate-without-ca --certificate-pem file://certs/0123XXXXXXXXXXXX01 --status ACTIVE    
{
    "certificateArn": "arn:aws:iot:ap-northeast-1:XXXXXXXXXXXX:cert/56366869fd...96b05161",
    "certificateId": "56366869fd8....096b05161"
}

aws iot attach-policy --target "arn:aws:iot:ap-northeast-1:XXXXXXXXXXXX:cert/56366869....96b05161" --policy-name wildcardpolicy
```

最後にデバイスからアクセスするエンドポイントURLを取得する

```
aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
    "endpointAddress": "XXXXXXXXXX-ats.iot.ap-northeast-1.amazonaws.com"
}
```

#ESP32でのテスト#

手元のESP32 Devkitを使い、AWSへの接続を試してみた。



AWS IoTの「テスト」画面から"test_topic/esp32"をサブスクライブすると接続ができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/8ef9447c-e047-85a0-feeb-a6ee2cab5064.png)
FlutterでSnackBarを共通部品化するのは意外と面倒だった

#SnackBarの記事は世に溢れている
FlutterでSnackBarを出す方法を調べると簡単に情報が出てくる。

```Dart
// ボタンを押したらスナックバーを出す
onPressed: () {
  // 変数snackbarの中に表示したい情報を詰める
  final snackbar = SnackBar(
      content: Text('10秒後に消えます'),
      action: SnackBarAction(
        label: '閉じる',
        // 閉じるボタンを押したら
        onPressed: () {
          Scaffold.of(context).removeCurrentSnackBar();
        },
      ),
      // 何秒後に消えるか
      duration: Duration(seconds: 10),
    );
  // ここで変数snackbarの中身を表示
  Scaffold.of(context).showSnackBar(snackbar);
},
```

しかしこのスナックバーをどこからでも呼び出せる共通部品にしようとした時、どうやってもうまくいかなかった。

色々模索した結果
・returnしない
・Builderで囲う
のがコツだとわかった

```Dart
// CenterをBuilderで囲ってcontextを渡せるようにしてあげる
body: Builder(builder: (BuildContext context) {
        return Center(
          child: Column(
            children: [
              RaisedButton(
                child: Text('スナックバー表示'),
                color: Colors.blue,
                textColor: Colors.white,
                onPressed: () {
                  // contextを引数にしてカスタムスナックバーに渡す
　　　　　　　　　　　// 他の変数も用意すれば渡せる
                  final snackbar = CustomSnackBar(context);
                  Scaffold.of(context).showSnackBar(snackbar);
                },
              ),
            ],
          ),
        );
      })



// スナックバーを部品化したクラス
class CustomSnackBar extends SnackBar {
// Widget build とか　returnは書かない
  CustomSnackBar(BuildContext context) : super(
    content: Text('10秒後に消えます'),
    action: SnackBarAction(
      label: '閉じる',
      onPressed: () {
        Scaffold.of(context).removeCurrentSnackBar();
      },
    ),
    duration: Duration(seconds: 10),
  );
}
```

Flutterはよくわからぬ…
カラーテーマ Cherry Petals 制作日記

VS Code のカラーテーマを自作したよ. 名前は桜っぽいから Cherry Petals. [リポジトリはこちら](https://github.com/MikuroXina/cherry-petals-theme).

![スクリーンショット](https://github.com/MikuroXina/cherry-petals-theme/raw/master/SS.png)

その制作日記風の読み物を置いておく.

非常に主観的な独自研究でやっているのでツッコミされても何も言えないし, 色の決定に関して参考にした文献もないよ. 自分用のカラーテーマだからね.

# コンセプトの決定

デフォルトや他のテーマに不満があったために, 自作テーマを作ることにした. 具体的には以下の不満があった.

- コントラストが強すぎて長時間の作業に向いていない
- コントラストが弱すぎて文字の判別がしづらい
- 使う部分以外の色が多く, 画面上に不必要な情報が多い

というわけで, これを補う感じで以下のコンセプトに基づいてカラーテーマを作っていく.

- ダークテーマ
- 長時間の作業でも目が疲れにくい
- 文字を判別しやすい
- あまり使わない部分ほど色数を減らす

# 背景色の決定

長時間見ていても疲れないように, 目に優しいと言われている緑色を暗くした色を使うことにした. 緑色を暗くした様々な色の候補を画面全体に広げて長時間眺めることで, どの色が背景色に適しているかを確かめた.

実験の結果, `#191d19` を使うことにした.

# アクセント色の決定

ハイライトしているアイテムやカーソルに用いる色を決める. 先程の背景色に対して, それぞれ色相が遠い色と近い色の 2 つを選ぶことにした.

ハイライトに使う色は, 早々と `#e6ade6` に決まった. 桜をイメージした淡いピンクのつもり. バッジや通知に使う色はこれを暗くした `#64004b` にした.

対して, カーソルの色には難航した. パット見でも迷わずにカーソルの位置がすぐにわかる明るめの色が必要だった. これは紫や青緑や黄を試した後に水色の `#00f7ff` に決まった. 実際には `#00f7ffbb` と少し透過させてある.

# 色のとり方

`#191d19`, `#e6ade6`, `#00f7ff` の三つを組み合わせて色を取っていき, 以下の法則に従って細かい色を決めていくことにした.

- 近い系列のモノの色は近くして, 遠い系列とは遠ざける
- 頻度の少ないものほど明るくして, 多いものは暗くする
- 頻度が偏るもの (選択中のテキストやコメント) はアクセント色に寄せる

# シンタックスハイライト

シンタックスハイライトをするために決めた大体の色とその理由を書いておく.

- 地の文 `#ccc`: ボーッとしていても集中していても見やすい灰色を試行錯誤した
- 変数 `#faeaab`: プログラム中で把握する必要がある存在なので, 地の文と同じくらいの明るさでどのアクセント色からも遠ざけた
- コメント `#e6ade6`: 連なっても点在しても目立ちやすく読みやすいようにするため第一アクセント色と同じ
- キーワード `#38b4aa`: 文法上重要な意味を持つが要らない情報であることも多いので背景色と第二アクセント色の中間
- リテラル `#5ab8cf`: 頻度は少ないが, 値自体を頻繁に眺める必要は無いため第二アクセント色を濁らせた
- 文字列 `#c3e88d`: 頻度が少なく値自体の意味も強いため背景色を明るくした
- クラス `#6b8eff`: それなりの頻度でかつ重要であるため第一アクセント色と第二アクセント色の中間
- `this` 系 `#158a4f`: 頻度が多いがこれ自体には意味がないため背景色を少し明るくした (暗めではある)
- 記号系 `#b89c69`: 単体は重要ではないため背景色と第一アクセント色の中間を暗くした

# セマンティックハイライト

公開してからしばらく後にセマンティックハイライトにも対応した. そのときに決めた色も同様に書いておく.

- インターフェイス `#a280cf`: より第一アクセント色を強くしてクラスとの違いを明確にした
- 関数 `#84d4b3`: 大量に書かれている可能性があるため, 背景色を明るくしつつ第二アクセント色に寄せた

---

# 参考文献

- [Theme Color | Visual Studio Code Extension API](https://code.visualstudio.com/api/references/theme-color)
完全な個人用メモ。DCモーターのゴムプーリー調査

##概要
130, 260, 540などの一般的なDCブラシモーターで動力伝達に使うプーリーやベルトの調達について調べた

##前提

今回はあまりトルクが必要ないと想定され、回転数もMAX2500くらいかなあと勝手に考えている。

> :pushpin: 頼まれた仕事的に、あまり重たいモーターは実用的ではないと思うので、軽いモーターで安く仕上げたいところ

## モーター

ミスミで調べた。たぶんこの辺がいい。
[モーターはこれ](https://jp.misumi-ec.com/vona2/detail/221006269389/)。プーリーもついてるっぽい。
[モーターベースはこれ](https://jp.misumi-ec.com/vona2/detail/221302669001/)。↑のモーターにも固定台がついてるっぽいが水平にしか置けなさそうなので却下。パネルマウントできそうなこっちを選んだ。

## ベルト
[これ](https://www.monotaro.com/p/1021/6334/)とか
[これ](https://www.monotaro.com/p/0750/3773/)とか。

モーターの写真についてるプーリーの大きさ的に線径φ1.8~2.0で良いような気がする。

## ドライバ

ちょうど良いサイトがあった。[ここ](http://project12513.blog-fps.com/%E5%91%A8%E8%BE%BA%E5%9B%9E%E8%B7%AF%E8%A8%AD%E8%A8%88/%E3%83%A2%E3%83%BC%E3%82%BF%E3%83%BC%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%82%92%E9%81%B8%E3%81%B6)。
[秋月のDRV8835](https://akizukidenshi.com/catalog/g/gK-09848/)が安くて良いかもしれない。

## 回転速度の取得

手元に反射型レーザー回転計があるので、それを使用。型番は「H0138」。made in china。
反射シールがついていて、それをプロペラのようなものに張り付けて使用する。
回転検知用のプロペラっぽいのもモーター軸のどこかに固定できるように考えなければ。


嫁の母の老健の入所イベントが明日に控えています。なかなか気が重い。
2020年10月13日
[Rails]deviseの導入

# はじめに
deviseとは、ユーザー管理機能を簡単に実装するためのgemです。

# 目次
1.deviseのインストール
2.deviseの設定ファイルを作成
3.モデルの作成
4.テーブルの作成
5.ビューの編集
6.コントローラーの編集
# 1. deviseのインストール
gemfileに以下を記述します。

```ruby:gemfile
gem 'devise'
```
アプリのディレクトリで以下を実行します。
##### ターミナル
```
bundle install
```

gemをインストールした後は**サーバーを再起動**します。
サーバーを再起動することでgemが反映されます。
##### ターミナル
```
rails s
```

# 2. deviseの設定ファイルを作成
deviseを使用するためには、gemのインストールに加え、 devise専用のコマンドで設定ファイルを作成する必要があります。
以下を実行することで、追加したdeviseというgemの「設定関連に使用するファイル」を自動で生成することができます。
##### ターミナル
```
rails g devise:install
```

# 3. モデルの作成
deviseを利用する際には、アカウントを作成するためのUserモデルを新しく作成する必要があります。
作成には通常のモデルの作成方法ではなく、deviseのモデル作成用コマンドでUserモデルを作成します。
##### ターミナル
```
rails g devise user
```

また、rails g deviseコマンドによりモデルやマイグレーションを自動生成するだけでなく、routes.rbにルーティングも自動的に追加されます。

# 4. テーブルの作成
必要なカラムを追加する場合は、マイグレーションファイルに記述し以下を実行します。
##### ターミナル
```
rails db:migrate
```

# 5. ビューの編集
カラムを追加した場合は、追加したカラムを入力できるように、新規登録画面のビューを編集する必要があります。
デフォルトでは、deviseのビューファイルは隠れているので、以下を実行します。
##### ターミナル
```
rails g devise:views
```

# 6. コントローラーの編集
また、コントローラーを編集したい場合は以下を実行することでdevise管理下のコントローラーを作成することができます。
##### ターミナル
```
rails g devise:controllers users
```
micro:bitのMakeCodeEditorの I2Cブロックが少しわかった

マイクロビット（micro:bit）のMakeCodeEditorでの、I2Cの書き込み規則が、少しわかったので、記事にしておきます。

#概要

- とりあえず、これで　INA226isoモジュールのコンフィグレジスタが　書き換えられたようです。
 - [使用したハードウェア:■INA226iso 絶縁I2Cディジタル電流・電圧・電力計モジュール(20Aタイプ) ](https://strawberry-linux.com/catalog/items?code=11226)
 - このモジュールのアドレスをGを二箇所、ハンダでショートして、アドレスを64（16進数 40H）に設定しています。
 - [コンフィグが書き換わったプログラム](https://makecode.microbit.org/_VH1Ppk4st5k8)
 - 最初だけのブロックでコンフィグワードの書き換え
 - ずっとのブロックでコンフィグワードを読み込み、シリアルに書き出しています。
 - これでマイクロビットに書き込んで実行
 - デバイスコンソールで、読み込んだコンフィグワードを確認しています。
 
![スクリーンショット 2020-10-13 18.22.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/ca9b1e41-32bb-b1ac-e9b5-0d804230968f.png)


#ポイント

- 一つの書き込み命令で　書き込み切るみたい。
![スクリーンショット 2020-10-13 18.04.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/8c7533d0-3043-a892-af1c-47b005d1dd4e.png)


- 以下をUInt32BEで、１ブロックで書き込みました。
0000 0000 0100 0101 0010 0111 0000 0000　→　１０進数　→　4531968（16進数 00452700）
〜〜〜〜　〜〜〜〜〜〜〜〜〜　〜〜〜〜〜
アドレス　コンフィグワード　　　ゴミ（無視）

- この10進数の値（453196）をUInt32BEで書き込みました.

![スクリーンショット 2020-10-13 17.57.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/7c67155c-20c5-4aaf-6026-898bb3be082c.png)

[I2Cの公式マニュアル](https://makecode.microbit.org/types/buffer/number-format)

#感想

- かなり嬉しい！これで、マイクロビットのブロックプログラミングで　いろいろなセンサモジュールが使えそうです。
- でも、8bit x 4 以上のコマンドは　書き込めないかも。。。。

#関連サイト

- [YouTube　簡単マイコン教室](https://www.youtube.com/channel/UC41qeaw-dXNdl0puKkXiuKA)
- [Scratch+microbit+Maqueenのプログラムの蔵【プロ蔵】](https://sites.google.com/view/prokura/)
- [簡単マイコン教室のページ](https://qiita.com/tmdoi/items/61be444e1879912aa2a5)
Google Analytics Reporting API v4を使ってPV数とUU数を取得する

#はじめに
[はじめてのアナリティクス Reporting API v4: サービス アカウント向け PHP クイックスタート](https://developers.google.com/analytics/devguides/reporting/core/v4/quickstart/service-php?hl=ja)を参考にして、指定した期間のPV数とUU数を、日毎に取得するバッチを作成できたので、クイックスタートのHelloAnalytics.phpのgetReportメソッド にあたる部分の備忘録。
cronでバッチ実行して日毎のPV数、UU数を取得するバッチを実行したい人の役に立てたらと思います。

##前提
- PHP7.4
- Google API ConsoleでJSON形式の秘密鍵を作成済み
- クライアントライブラリインストール済み
- 例外系の処理も書いていますが省略。

###PHPプログラム
```HelloAnalytics.php
<?php

function getReport($analytics) {

    // Create the DateRange object.
    $dateRange = new Google_Service_AnalyticsReporting_DateRange();
    $dateRange->setStartDate("7daysAgo");
    $dateRange->setEndDate("today");

    // Create the Metrics object.
    // PV
    $pageviews = new Google_Service_AnalyticsReporting_Metric();
    $pageviews->setExpression('ga:pageviews');
    // UU
    $uniqueUsers = new Google_Service_AnalyticsReporting_Metric();
    $uniqueUsers->setExpression('ga:users');

    // Create the Dimension object.
    // Daily
    $byDay = new Google_Service_AnalyticsReporting_Dimension();
    $byDay->setName("ga:date");

    // Create the ReportRequest object.
    $request = new Google_Service_AnalyticsReporting_ReportRequest();
    $request->setViewId($viewId);
    $request->setDateRanges($dateRange);
    $request->setMetrics([$pageviews, $uniqueUsers]);
    $request->setDimensions([$byDay]);

    $body = new Google_Service_AnalyticsReporting_GetReportsRequest();
    $body->setReportRequests([$request]);
    $result = $analytics->reports->batchGet($body);

    //今回は日毎のPV数とUU数が欲しかったので、日付をキーとした連想配列にpvとuuを入れてみました。
    $data = [];
    foreach ($result['reports'][0]['data']['rows'] as $row) {
        $data[$row['dimensions'][0]] = [
            "pv" => $row['metrics'][0]['values'][0],
            "uu" => $row['metrics'][0]['values'][1],
        ];
    }
```

実際の中身の形式は以下のようになります。

```
    var_dump($data);
    //以下結果例
    [20201013] =>
     array(2) {
     'pv' =>
         string(5) "12345"
     'uu' =>
         string(4) "8585"
     }...
```


###最後に
ソートの設定しなくても古い順から結果を得ることができるんですね。
クイックスタートの参考例ではPV数だけが返ってきており、かつ指定した合計数が返ってきてしまったのですが、

    $uniqueUsers->setExpression('ga:users');
    $byDay->setName("ga:date");

こちらの設定をすることで、PV数だけでなくUU数と、指定した期間の日毎の結果を得ることができたので嬉しかったです。
What is LWDM (Lan Wavelength Division Multiplexing)

There are CWDM(coarse wavelength division multiplexing),DWDM(dense wavelength division multiplexing),and newly MWDM,LWDM in 5G WDM bearer solutions. MWDM and LWDM are two kinds of WDM proposals presented by China Mobile and China Telecom. MWDM reuses the first 6 waves of CWDM, compresses the wavelength interval to 7nm, and expands it to 12 waves with a 3.5nm offset.

And LWDM is based on the Ethernet channel wavelength division multiplexing Lan-WDM technology, also known as dense wavelength division multiplexing. Its channel interval is 200~800GHz, this range is between DWDM (100GHz, 50GHz) and CWDM (about 3THz). LWDM uses 12 wavelengths in the O-band range from 1269nm to 1332nm, with a wavelength interval of 4nm (Wavelengths including 1269.23, 1273.54, 1277.89, 1282.26, 1286.66, 1291.1, 1295.56, 1300.05, 1304.58, 1309.14, 1313.73 , 1318.35nm).

![154.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/5181425d-5f20-0f8f-94b1-ee00b52b1d9f.jpeg)
 
The characteristic of LWDM working wavelength is that it is located near zero dispersion, with small dispersion and good stability. At the same time, LWDM can support 12-wave 25G to increase the capacity and save fiber. 

HYC can provide customers with a full range of WDM solutions, including the latest MWDM, LWDM and CWDM, DWDM products. HYC has 20 years of OEM/ODM manufacturing experience in the optical communication industry, and has a certain influence in the global industry. It focuses on providing customers with one-stop customization of the design, development and manufacturing of passive basic optical components for optical communication. The production lines includes fiber optic connectors, fiber optic jumpers, PLC splitters, WDM wavelength division multiplexers, MEMS optical switches, and so on. Products are widely used in FTTH, data centers, 5G networks, and telecommunication networks.
https://hyc-system.com/Product/index_208