OmniAICreator/Qiita-1.07M huggingface dataset:
JSやCSSにクエリストリングを与えてファイル更新時にブラウザ側のキャッシュクリアを行わせる

# はじめに
タイトルの内容で記事を書いた理由は、「キャッシュクリアの為にファイル名の後ろに数字をつけるアレ」と曖昧な覚え方をしていたからです。
曖昧な覚え方だとググることすらもできなかったので、備忘録として記事にしました。

# Cache Busting
Javascript、CSS、画像等のファイルの更新に合わせてクエリストリングを変更することで、ブラウザ側でキャッシュクリアをしなくてもいい状態にすることです。
ブラウザ側がサーバ側のファイルを読み込まずキャッシュを読み込むことでJavascript、CSS、画像の修正が反映されないことを防ぎます。

# 後ろにつけるアレの正式名称を覚えたい
- クエリ
- クエリストリング
- クエリ文字
- GETパラメータ
- パラーメータ

特に固定された呼び方はないのでしょうか。
個人的にクエリストリングがしっくりきたのでクエリストリングと呼びつつ他にこういう言い回しもあるという程度に覚えておきます。

# 具体例
Javascript、CSS、画像ファイルの後ろに`?クエリストリング`と記述します。
CSSファイルの読み込みを例として、クエリストリングを書いてない場合は

```
<link rel="stylesheet" type="text/css" href="/css/default.css" />
```

クエリストリングを書いている場合は

```
<link rel="stylesheet" type="text/css" href="/css/default.css?20210909" />
```

と記述します。

# CakePHPでヘルパーを利用してタグを作成した場合にクエリストリングを付与
## 環境
### ソフトウェアのバージョン
PHP 7.3.15
CakePHP 2.10.20

## HtmlHelper利用時にクエリストリング付与
### パラメータ無しでクエリストリングを付与
パラメータの`$url`にクエリストリングを付与したファイル名を記述します。

```index.ctp
<?php $this->Html->css('test.css?20210909', array('inline' => false)); ?>
```

出力結果は以下の通りです。

```
<link rel="stylesheet" type="text/css" href="/css/test.css?20210909"/>  
```

### パラメータありでクエリストリングを付与
パラメータの`$url`にクエリストリングを付与したファイル名を記述する際にパラメータを記述します。

```index.ctp
<?php $this->Html->css('test.css?param=20210909', array('inline' => false)); ?>
```

出力結果は以下の通りです。

```
<link rel="stylesheet" type="text/css" href="/css/test.css?param=20210909"/>  
```

## Configureを利用してクエリストリングを付与
クエリストリングが複数ある場合に同時に修正したかったので、Configureを利用してみました。
Configディレクトリに設定用のファイルを作成し、設定したいクエリストリングを記述します。

```testConfig.php
<?php
$config['reloadQuery'] = '20210909';
```

Configディレクトリの`bootstrap.php`に設定ファイル読み込みの記述をします。

```bootstrap.php
Configure::load("testConfig.php");
```

Controllerでクエリストリングを受け取り、テンプレートに渡します。
テンプレートが複数ある場合に共通化した処理になると考えたため、`AppController.php`に`beforeFilter()`を記述してクエリストリングを受け取っています。

```AppController.php
class AppController extends Controller {
	public function beforeFilter() {
		$reloadQuery = Configure::read('reloadQuery');
		$this->set(compact('reloadQuery'));
	}
}
```

Controllerから受け取った`$reloadQuery`をテンプレートで使用します。

```index.ctp
<?php $this->Html->css('test.css?' . $reloadQuery, array('inline' => false)); ?>
```

出力結果は以下の通りです。`test.css?`の後ろに`testConfig.php`で設定した値が表示されます。

```
<link rel="stylesheet" type="text/css" href="/css/test.css?20210909"/>  
```

`index.ctp`よりも外側のテンプレート(例：`default.ctp`)があるとして、そこで直接タグを書いている場合は以下のように記述します。

```default.ctp
<?php <link rel="stylesheet" type="text/css" href="/css/default.css?<?php echo $reloadQuery; ?>" /> ?>
```

出力結果は以下の通りです。

```
<link rel="stylesheet" type="text/css" href="/css/default.css?20210909" />
```

# そもそもCakePHPだったらコメントアウトを外すだけ？
そもそもCakePHP2.xだと`core.php`に記述されている以下のコメントアウトを外すだけでキャッシュクリアを行ってくれるようでした。

```core.php
Configure::write('Asset.timestamp', 'force');
```

コメントが英語だったのでしっかりと理解できていませんでしたが、おそらくブラウザを開くたびに毎回キャッシュクリアをする設定だと思います。
今回の目的はファイル更新後に1度だけキャッシュを読み直して欲しかったので上記の設定は使わなかったです。

# 参考にさせてもらったサイト
https://netamame.com/cache-busting/

https://book.cakephp.org/2/ja/core-libraries/helpers/html.html

https://kengotakimoto.com/post-2174/

https://fu-tara.com/how_to_solve_easily_with_cache_busting_in_cakephp2/


以上です。
【Firebase / Flutter Web】Firestoreセキュリティールールの関数サンプル

```js
//firesotre.rules

  //作成可能なフィールドかチェックする関数
  function isAvalableFieldOnCreate(fieldList){
      return request.resource.data.keys().hasOnly(fieldList)
    }
  //※ fieldListに作成を許可するフィールド名を配列で渡す。
  //※ request.resource.data =>作成しようとしているデータを取得
  //※ keys() => データーのキーを取得
  //※ hasOnly() => 含まれていたらtrue 含まれていなかったら false
  //※ 結果、作成しようとするデータに許可されていないフィールドが含まれていたらNGとなる。

```
```js
//firesotre.rules

//更新可能なフィールドかチェックする関数
  function isAvalableFieldOnUpdate(FieldList){
      return request.resource.data.diff(resource.data).affectedKeys().hasOnly(FieldList)
    }
  //※ fieldListに更新を許可するフィールド名を配列で渡す。
  //※ request.resource.data =>作成しようとしているデータを取得
  //※ diff(resource.data) => 変更前との差分を取得
  //※ affectedKeys() => 変更があったデータのフィールドを取得。
  //※ hasOnly() => 含まれていたらtrue 含まれていなかったら false
  //※ 結果、作成しようとするデータに許可されていないフィールドが含まれていたらNGとなる。
```

```js
//firesotre.rules

  //update禁止なフィールドが含まれているかチェックする関数
  function isContainProhibitedField(fieldList){
     return request.resource.data.diff(resource.data).affectedKeys().hasAny(fieldList);
    }
  //※ fieldListに更新を許可するフィールド名を配列で渡す。
  //※ request.resource.data =>作成しようとしているデータを取得
  //※ diff(resource.data) => 変更前との差分を取得
  //※ affectedKeys() => 変更があったデータのフィールドを取得。
  //※ hasAny() => 含まれていたらfalse 含まれていなかったら true
  //※ 結果、作成しようとするデータに許可されていないフィールドが含まれていたらNGとなる。
```


```js
//firesotre.rules

  // 作成しようとしているドキュメントのuidフィールドがログイン中ユーザーのuidと一致しているか
  function isUidFieldEquelToLoginUid(){
    return request.auth.uid == request.resource.data.uid
  } 
  //※ request.auth.uid =>ログイン中のUIDを取得
  //※ request.resource.data.uid => 作成しようとしているデータのuidフィールの値を取得
  //※ 結果、作成しようとしているデータのuidフィールドの値がログイン中のuidと異なったらNGとなる。
```


```js
//firesotre.rules

  // 参照・更新しようとしているドキュメントのuidフィールドがログイン中ユーザーのuidと一致しているか
  function isResouseUidFieldEquelToLoginUid(){
    return request.auth.uid == resource.data.uid
  }  
  //※ request.auth.uid =>ログイン中のUIDを取得
  //※ resource.data.uid => 参照しようとしているデータのuidフィールの値を取得
  //※ 結果、参照・更新しようとしているデータのuidフィールドの値がログイン中のuidと異なったらNGとなる。
```

```js
//firesotre.rules

  // ドキュメントidが自分のログイン中のユーザーのuidと一致するか。
  function isDocIDEquelToLoginUid(userID){
     return request.auth.uid == userID
  }

  //関数呼び出し例

     match /users/{userId} {
    	allow get : if isDocIDEquelToMyUID(userId));
    }
```

参考
https://cloud.google.com/firestore/docs/security/rules-fields?hl=ja
テックキャンプ を受講した感想


##自己紹介
前職　メーカー営業を3年半勤め退職しました。
プログラミングに興味などが湧き、転職のためテックキャンプ　なんばスカイ校に受講!!
**結果的に、自社開発から2社内定をいただきました。**

テックキャンプに入ってよかったかどうか私の判断になるので、参考程度に興味ある方は読んでください。

##結論：入ってよかったと思います
良かった点
**・未経験からでも分かりやすい教材になります。
・未経験からプラグラミングの独学だと諦めてしまう可能性もありますが、教えてくれる方がいる。
・同じ未経験からエンジニアを目指している方達と知り合え、教え合いが可能になる。
・エラーが出たときに、調べ方や教えてくれる方がいる。**

私は、一人でずっと勉強できる性格ではなかったので、そういった方はスクールに行くのがいいかもしれません。

ただ、誰かにお勧めできるかはなんとも言えません。

##なぜお勧めするか悩む理由
**・料金が高すぎる。
・転職サポートはあってないようなもの。（関西だけかもしれない）
・担当される社員に当たり外れがある。
・言語がRubyでなくても良い。（これも関西は別言語でも良い）**

３ヶ月での受講で約75万ほどでした。受講後に転職サポート１年間がついているが、ほぼあってないようなものだと感じた。これは関西側だからというのもあるかもしれません。

転職サポートは、関西だと少なく関東だと圧倒的に多かったです。記憶が正しければ約５ヶ月の内に紹介してくれた会社は３、４社ほどで、仕事の内容も全く希望に沿うものではなかった印象です。それを知れたのは一緒に受講していた方達が関東に転職される方で、紹介された会社が多かったからです。**だから返金保障制度も関東での転職されない方は、返金対象にならないのでしょう。**

関西で転職される方は、ほぼ自力での転職になる覚悟はもった方が良いです。
９９％の転職成功率という数字では、安心を持たない方が良いです。

##学ぶ言語について（関西なら）
テックキャンプでは、**Ruby**という言語を使用して学習します。
他にもHTML/CSS、JavaScriptなど学びますが、ほぼ**Ruby**です。

**Rubyの需要は、関東の方が大きいです。
関西では転職する上でRubyを使える会社は少ないです。**

やるなら**JavaやJavaScript、Pythonをお勧めします。**
私が転職できた部分としては、独学でそれらを勉強してポートフォリを作成したことが大きいと思います。

情弱である私自身がもっと調べるべきでもあったので、言語については特に文句があるとかではありません。

##なぜテックキャンプにしたのか
正直、マコなり社長のYouTubeが大きいです。だいぶ前からYouTubeを見ていたので、受講しようと思いました。ただ、テックキャンプで教えてくれる方が全員優秀な人とは言えません。確実にマコなり社長と比べてみてしまってたので、そういう印象です。

どこか会社に入社する時なんて、会社の社長なんてわからないものだと思います。
しかし、マコなり社長はYouTubeで色々動画を上げているのでどうしても比べてしまい、そこまで社員の方がいいとは感じませんでした。いい人もいますよ！！！

##まとめ
私自身はお勧めで悩むと記載しましたが、テックキャンプでも色々やり方を変えていってるみたいなので、よくなっているかもしれません。

現在は給金制度もあるみたいなので、確実に安く受けれる。
俺もこのときに受けたかった、、笑

https://tech-camp.in/expert/grant?utm_source=google&utm_medium=ls&utm_campaign=name&gclid=CjwKCAjwvuGJBhB1EiwACU1AiXmopVvIrK6MH4hIOotg6zBfXDOme-6BfSkbiQmuraw0BDPrAa69kRoCP7kQAvD_BwE

一人で独学が厳しいと感じるのであれば、受けてみるのもアリなのかもしれません。

他に質問等あればお気軽に聞いてください。
以上
ログイン実装について、Devise／Warden／Rack の関係を一言で

Rails のログイン実装でお馴染みの Devise について調べたため、メモを残します。引用元を合わせて記します。

<h1>Devise とは？</h1>
・Rails に認証を実装するためのソリューションのこと
・<b>Warden</b> がベースになっている
> Devise is a flexible authentication solution for Rails based on <b>Warden</b>.
> −− [Github](https://github.com/heartcombo/devise)

<h1>Warden とは？</h1>
・<b>Rack</b> 内で、認証するメカニズムを与えてくれるもの

> Warden provides a mechanism for authentication in <b>Rack</b> based Ruby applications.
> −− [Github](https://github.com/wardencommunity/warden/wiki)

つまり、
1. Rack 内で、
2. Warden というものが認証するメカニズムを提供し、
3. Deviseがそのメカニズムを Rails に実装してくれる。
ということですね！



<h1>Rack とは？</h1>
・Ruby で、WEB開発をするためのインターフェースを与えてくれるもの
・HTTPリクエストとHTTPレスポンスを束ねて、APIとし、シングルメソッドコールにしてくれるもの（要は、Rack のおかげで API が打てるということですね）

> Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby.　By wrapping HTTP requests and responses in the simplest way possible, it unifies and __distills the API__ for web servers, web frameworks, and software in between (the so-called middleware) __into__ a single method call.
> −− [Rails guides](https://guides.rubyonrails.org/rails_on_rack.html)

ちなみに、この文章での distills the API（一般的に distills は「蒸留する」）の意味が最初は謎でした。（APIを蒸留するとは…？）<br>そこで、オックスフォード英英辞典を参考にしました。↓↓
> <b>distil</b> sth (from/__into__ sth) 
> to get <b>the essential meaning</b> or ideas from thoughts, information or experiences
> -- Oxford Academic English

なるほど、distills には「インフォメーションからエッセンシャルなものを取り出す」というような意味合いがあるみたいですね。参考にしてください。

<h1>まとめ</h1>
Rack 内で、Warden による認証メカニズムを、 Devise が Rails に実装してくれる。
連番＋テキストのファイル名修正

忘れないようにしておくためのメモ

■今回環境
Windows10（Powershell） + EXCEL
→フリーソフトは使用不可

連番プレフィックスのファイル名について、連番部分のみを変更する
例．）
1_あい.xlsx
2_うえ.xlsx
3_おか.xlsx
4_きく.xlsx
...
99_hoge.xlsx
ここの数字だけを全ファイル分カウントアップ

１．）外部ツールが使用可能であればそれを使う
→今回は隔離された環境なので使用不可

２．）力技で人力修正
→数ファイルならこれだけど、今回は苦痛なのでナシ

３．）今回の頭の体操
以下手順
Ⅰ.)Powershellで該当ファイルがある任意ディレクトリにアクセスしてファイルリスト抽出
Get-ChildItem -Name
（個人的には ls -Name ですが）

Ⅱ．）ファイルリストをEXCELに貼り付け
A2セルにペタリ

Ⅲ．）昇順ソート
桁違いプレフィックス付きのファイル名は通常ソートしても
1_
11_
12_
..
2_
21_
の並びになってしまうので、プレフィックス部分を数値として抽出して
それを昇順ソートします。

B1セルに
=value(left(A2),find("_",A2)-1))
を入れて、プレフィックスの数値を抽出
ファイル名が入った行全部にコピーして、数字を出力。
A1とB1のセルを選んでフィルタ、B列で昇順ソートする。

Ⅳ．）ファイル名のテキスト部のみの抽出
C列にテキスト部を出力しておきましょう。
C2セルに
=right(A2,(len(A2)-find("_",A2)+1))
をいれると、プレフィックスなしのファイル名が抽出できるので、
ファイル名が入った行全部にコピーして、テキスト部を出力。

Ⅴ．）連番部分とガッチャンコ
D2セルに新しいファイル名を生成しましょう。
=B2+1&C2
+1の数値は要件に合わせて任意に変更してください。
ファイル名が入った行全部にコピーして、新しいファイル名を出力。

Ⅵ．）Powershell用コマンド生成
ren "旧ファイル名" "新ファイル名"
としたいので、E2列に以下のおまじない生成関数を入力
="ren """&A2&""" """&D2&""""
ren "1_あい.xlsx" "2_あい.xlsx"
出力されていれば、期待値通りにできてますよ。

ファイル名が入った行全部にコピーして、おまじないを出力。

Ⅶ.）おまじないをPowershellにコピペ
あとはコマンドざーっと流したら出来上がりです。
ごちそうさまでした。
Bootstrap フォームの色（枠）の変更方法

```html
<form>
  <div class="form-group">
    <input type="text" class="form-control">
  </div>
</form>
```
↓に変更

```html
<form>
  <div class="form-group">
    <input type="text" class="form-control border-success">
  </div>
</form>
```

inputのclassの部分に

```html
border-success（今は緑色）
```

を挿入するだけ！！！

#カラー表
https://getbootstrap.jp/docs/4.3/utilities/colors/
ECSの環境変数をSecretsManagerに保存する

機密情報SecretsManagerに登録する方法です。

### SecretsManagerにシークレット情報を保存する

#### シークレットを保存

```
aws secretsmanager create-secret \
--region ap-northeast-1 \
--name MY_SECRET \
--secret-string XXXXX
```

#### 保存したシークレットを確認したい場合
```
aws secretsmanager get-secret-value \
--secret-id MY_SECRET \
--query 'SecretString' 
```

### ECSのタスク実行ロールにシークレットマネージャーへのアクセス権限を付与する

コンテナからシークレットマネージャーの値にアクセスするためには、以下2つの設定が必要です。
1. タスク実行IAMロールを設定する
2. タスク実行IAMロールに、シークレットマネージャーの指定リソースへアクセスを許可するポリシーを設定する

コンテナからはIAMロールを使ってシークレットマネージャの値を取得します。

1は定義済みとして進めます。まだタスクにロールが設定されていない場合は[こちら](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_execution_IAM_role.html)を参照。

* IAM > ロール から設定したECSタスク実行ロールを選択
![121506920-28120a80-ca1f-11eb-85df-4fd89ca01ec3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/9b6fe12a-a342-1684-35f2-77365717856c.png)

* インラインポリシーの追加を選択
![121507126-51329b00-ca1f-11eb-9ecd-e61e682b8623.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/d6d69676-a1ec-6474-d45f-8440bd32084a.png)


* JSONエディターで以下を貼り付ける。リージョン、アカウントID、シークレット名は修正

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": [
                "arn:aws:secretsmanager:ap-northeast-1:11111111:secret:my-secret"
            ]
        }
    ]
}
```

![121507507-aa9aca00-ca1f-11eb-9efe-e32e8d7043fb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/95704c9a-1bab-a9c8-c648-664325949264.png)


## 参照
* [公式チュートリアル](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/specifying-sensitive-data-tutorial.html)
オイラ、オイラーの等式が書きたかったんだッ！

とある社内のSlack投稿を見て、「あ゛」とか「ま゜」とか書けるようになった。
「゛」は「だくてん」と書いて変換すると出る。
「゜」は「はんだくてん」と書いて変換すると出る。
（ちなみに、WindowsのIMEを使っています。）

おお、なんか嬉しい。小さい２とか小さい３とかも変換するだけで書けるぞッ！
と、調子に乗って世にある有名な公式を書き殴っていった訳ですが、世界一美しいと言われている「オイラーの等式」がどうしても書けない。。
アルファベットの上付き文字とかどうやって書くの？

で、ググってみたところhtmlでは書けそうだったので、この記事で実験してみました、という話。

***e*<sup>iπ</sup>+1＝0**

おお~書けました！

めでだし、めでたし。

（参照）
https://hensa40.cutegirl.jp/archives/4857
物体検出の学習済みモデル使ってみた

# 学習済みモデルのダウンロード
openimagev4と呼ばれるデータセットで訓練したSSD(Single Shot MultiBox Detector)というモデルを使ってみました

# openimagev4
https://storage.googleapis.com/openimages/web/download_v4.html

600種類のクラスはここから確認できます
https://storage.googleapis.com/openimages/2018_04/class-descriptions-boxable.csv

# 実際に使ってみる
https://tfhub.dev/google/openimages_v4/ssd/mobilenet_v2/1
圧縮されたフォルダを展開してロードするだけです。

```python
modelpath = "./openimages_v4_ssd_mobilenet_v2_1" #"./faster_rcnn"
model = hub.load(modelpath).signatures['default']
```

入力はTensorです

```python
def load_img(path):
  img = tf.io.read_file(path)
  img = tf.image.decode_jpeg(img, channels=3)
  return img

localpath = os.path.join(dpath, fname)
image = Image.open( localpath )
tfimg = load_img( localpath )
converted_img  = tf.image.convert_image_dtype(tfimg, tf.float32)[ tf.newaxis, ... ]

result = model(converted_img)
```

# 検出結果

![18084_02S.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268835/f2dabc68-c9c3-51ec-05bd-a8f99ed42ead.jpeg)

![18084_02S.jpg_Car_97%_4cc9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268835/17e40521-0334-b644-53ed-63d3e3034b3f.jpeg)

# 速度と精度

速度だと
yolo > ssd > faster-rcnn
精度は
faster-rcnn > ssd > yolo
という認識です

480x270pxの画像を使って、faster-rcnnという精度重視のモデルと比較してみました


| モデル/速度平均値(秒/枚) | Geforce RTX 2080 Ti(7.5) |
| ----                    | ----                     |
| ssd                     | 0.2                      |
| faster-rcnn             | 2                        |

標準偏差は0.001程度でほぼ無視できます

時間あれば適合率も出しますね

# 残念なとこ
転移学習はできないみたいです。
https://github.com/pythonlessons/TensorFlow-2.x-YOLOv3

# そーす
https://github.com/yusukem99/imagev4clip
【MPAndroidchart】 棒グラフの横軸を動的に変更したいときに頭に入れておくとよいかも？な点

##概要
Androidアプリ　[ツケ台帳](https://play.google.com/store/apps/details?id=com.chelak.tsuke_daicho)　のツケ金額の解析画面を作る際、
MPAndroidの棒グラフ横軸を動的に変更(要素数に合わせて本数変更)したのですが、
若干詰まったのでメモ
 アプリの解説、過去の投稿は→[こちら](https://qiita.com/n_ku/items/de1675af32ca53acc562)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344513/c7034df4-e967-3c04-382b-1948335233bf.png" width="160" height="326" class="jop-noMdConv"><a href='https://play.google.com/store/apps/details?id=com.chelak.tsuke_daicho&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Google Play で手に入れよう' src='https://play.google.com/intl/en_us/badges/static/images/badges/ja_badge_web_generic.png'/ width="300"></a>

##起きた現象
listで設定した以上の数の軸が表示されてしまう。
(※本当はtestmen2、testの2軸のみ表示したい)
![e34822af256f7ffb3163ebf638651280.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344513/156b912f-78b6-2b90-3b38-149d20cc2dbb.png)
おそらく、listで指定されていないインデックスの要素はリストの最後の要素（この場合は test）とするという仕様なのではないかと思われます。

##解決方法
ラベルの個数を明確に指定してあげました。

```kotlin:HogeActivity.kt
barchart.xAxis.apply {
    LabelCount = xLabel.size = 1 //ここで明示的にラベル個数を指定
    //...
}
```


明示って大事ですね。
「gcloud auth application-default print-access-token」でトークン取得するまで

サービスアカウントでトークン取得するまでの覚書です。

#環境
Windows10
Google Cloud SDKインストール済み
https://cloud.google.com/sdk/docs/install?hl=JA

Google Cloud Platformでサービスアカウントを発行、プロジェクトIDとサービスアカウントをメモしておきます。

#サービスアカウントのキーを発行
Google Cloud SDKで以下のコマンドを実行します。
※この後の作業のためにロールをオーナーにしていますが、終わったら戻しておきます。

```shell
gcloud projects add-iam-policy-binding [プロジェクトID] --member="serviceAccount:[サービスアカウント]" --role="roles/owner"
```

変更したら、続けて以下コマンドを実行します。

```shell
gcloud iam service-accounts keys create [キーのファイル名].json --iam-account=[サービスアカウント]
```

成功するとローカルにJSONファイルが作成されます。
私の環境ではSDKのインストールディレクトリ内に作られていました。

#環境変数を登録する
作成したJSONファイルを環境変数に登録します。

```shell
set GOOGLE_APPLICATION_CREDENTIALS=C:\Users\[ファイルまでのパス]\[キーのファイル名].json
```

#トークン発行
```shell
gcloud auth application-default print-access-token
```
できた！
![スクリーンショット 2021-09-09 16.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308640/9d0f6a8c-ceb5-8817-8a86-3900f80ae215.png)
何気に面倒なのであんまりやりたくないですね。
DockerでAmplifyCLIを動かす

# 概要

* Local開発環境を汚したくないのでDocker環境を作る
* Amplifyの使い方自体は紹介しません

## tree

```
.
├── aws_configure
│   ├── config
│   └── credentials
├── docker
│   ├── Dockerfile
│   └── requirements.txt
├── src
│   ├── amplify
│   └── src
├── docker-compose.yml
└── .gitignore
```

## Dockerfile
```dockerfile
FROM python:3.8-buster

RUN apt update && apt -y upgrade \
&& apt install -y nodejs npm \
&& npm install -g @aws-amplify/cli

# java for Amplify Mock
RUN wget -O- https://apt.corretto.aws/corretto.key | apt-key add -
RUN apt install -y software-properties-common \
&& add-apt-repository --yes 'deb https://apt.corretto.aws stable main' \
&& apt -y update && apt install -y java-11-amazon-corretto-jdk

# COPY docker/requirements.txt /tmp/
# RUN pip install --upgrade pip && pip install -r /tmp/requirements.txt
```

amplify mockを使用するため、Javaをインストールしています
pythonで使いたいパッケージがあれば　`docker/requirements.txt` を用意して最後2行のコメントアウトを外してください


参考
* [Amazon Corretto 11 のインストール手順 -AWS Doc](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/generic-linux-install.html)
* [Install the Amplify CLI](https://docs.amplify.aws/cli/start/install/)
* [はじめての Amplify デプロイまで -Qiita](https://qiita.com/Tomoyuki_Mikami/items/a6f5b8803e58989c11c6)
* [Ubuntu Linuxで、add-apt-repositoryしようとして「コマンドがない」って言われたら](https://kazuhira-r.hatenablog.com/entry/20160116/1452933387)

## docker-compose.yml
```docker
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: docker/Dockerfile
    container_name: amplifyApp
    volumes:
      - ./src:/var/app
      - ./aws_configure:/root/.aws
    working_dir: /var/app
    tty: true
```

ソースコード置き場と、aws設定ファイル置き場をvolumesに設定します
`aws_configure` 以下のファイルは、`amplify init` すると作成されます
チーム開発など、設定ファイルがすでにある場合はここに保存しておきます
`aws_configure/credentials` はcommitすると大変まずいので、`.gitignore` で除外しましょう

## 起動

```bash
docker compose build
docker compose up -d
docker exec -it amplify-fastapi /bin/bash
```
Laravel8でAdminLTE3を使用する方法

# 概要

この記事では、管理画面として有名なテンプレート`AdminLTE3`をLaravel8で使用する方法について記述していきます。
前提として、既にLaravelのセットアップは完了している事としています。


# Laravel-AdminLTEをインストールする

下記の通り`composer`コマンドを使ってLaravel-AdminLTEをインストールします。

```
$ composer require jeroennoten/laravel-adminlte
```

インストールが完了したら下記のコマンドで`adminlte`コマンドが使えるようになっている事を確認します。

```
$ php artisan list
```

上記のコマンドを実施した結果、下記のようなリストが表示されます。

```
  adminlte
  adminlte:install     Install all the required files for AdminLTE, and additional resources
  adminlte:plugins     Manages the installation and removal of additional AdminLTE plugins
  adminlte:status      Checks the installation status of the AdminLTE resources
  adminlte:update      Update all the required assets for AdminLTE
```

念のため日本語解説版を紹介

```
  adminlte
  adminlte:install     AdminLTE に必要なすべてのファイル、および追加リソースをインストールします。
  adminlte:plugins     追加のAdminLTEプラグインのインストールと削除を管理します。
  adminlte:status      AdminLTE リソースのインストールステータスをチェックします。
  adminlte:update      AdminLTE に必要なすべてのアセットをアップデートする。
```

では、早速インストールコマンドを実行！

```
$ php artisan adminlte:install
```

インストールが成功すると、下記の差分が出来上がります。

**更新されたファイル**

- composer.json
- composer.lock

**新たに出来たやつ**

-  config/adminlte.php
-  public/vendor/
-  resources/lang/vendor/

上記の通りになっていれば、インストール完了です。

# 認証画面(View)の作成

下記のコマンドを実行して認証用のViewを作成します。
ViewはMVCのVの部分ですね。

```
$ php artisan adminlte:install --only=auth_views
```
`Authentication views installed successfully.`と出れば成功です。

resources/views/authフォルダの中身が、AdminLTE用に置き換わっているはずです。

下記のように`resources\views\auth\login.blade.php`の中身を見ると`adminlte`の記述がちゃんとあるはずです。

```
@extends('adminlte::auth.login')
```

上記は、`vendor/jeroennoten/laravel-adminlte/resources/views/login.blade.phpのファイルが参照されています。`が参照されていることになります。

# 認証画面以外にもAdminLTEを適用する

下記のコマンドを実行しましょう。
```
php artisan adminlte:install --only=main_views
```
すると、下記のようになります。

**新しくできたやつ**

- resources/lang/vendor/
- resources/views/auth/
- resources/views/vendor/

# ログイン後の画面を作成する

`resources/views/home.blade.php`を下記のようにします。

```php
@extends(‘adminlte::page’)

@section(‘title’, ‘Dashboard’)

@section(‘content_header’)
<h1>Dashboard</h1>
@stop

@section(‘content’)
<p>Welcome to this beautiful admin panel.</p>
@stop

@section(‘css’)
<link rel=”stylesheet” href=”/css/admin_custom.css”>
@stop

@section(‘js’)
<script> console.log(‘Hi!’); </script>
@stop
```

あとは、実際にログインしてみると、AdminLTEのデザインに置き換わっているはずです。

以上。

# 出典

下記のページを参考にさせていただきました。YOSHITAKAさんありがとうございます。
[Laravel8でAdminLTE3をターミナルで導入して、インストールする方法。管理画面をサクッと作ろう。](https://cross-accelerate-business-create.com/2021/01/02/laravel8-adminlte3-install/)
【python, jupyter lab】ファイルがあるのにno such file or directoryが出たら

```python
import os
path = os.getcwd()
print(path) 
# 例： /workspace
```
を実行してみてください(カレントディレクトリを表示します)。
**なぜかカレントディレクトリが、そのipynbファイルの置き場所じゃなかったりすることがあります**。

出力を確認してみて、 

想定していたカレントディレクトリ = 出力

ではなかった時は、以下を実行。

```python
os.chdir('/workspace/hoge/') # ← 変更したいディレクトリを入れてください。
```
で、カレントディレクトリを変えればOKです。

念のためチェック

```python
path = os.getcwd()
print(path) #/workspace/hoge
```

簡単な話ですが、ipynbファイルの置き場所を無条件にカレントディレクトリとして参照するものだと思っていたので、案外はまりました。

コード一部 引用：https://note.nkmk.me/python-os-getcwd-chdir/
画面をタップしたことを検知して処理をさせる。（UITapGestureRecognizer( )）

#今回の内容
<img width="150" alt="EE2BE1EC-8F38-41FF-B809-1187B4659E81_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/de52b69b-f653-9e3f-5ec9-93dac62a84ca.jpeg"> <img width="149" alt="5BAD35B0-115E-4AAE-80A1-5266D42A916D_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/7d03436d-e185-5424-48cf-c5421d018af5.jpeg">

#コードと簡単解説
 * `UITapGestureRecognizer(target: self, action: #selector(メソッド名))`でタップ時の処理を作成します。
 
 * `viewなど.addGestureRecognizer(インスタンス)`でタップした時に処理が働くようになります。

```Swift:ViewController
import UIKit

class ViewController: UIViewController {

    
    @IBOutlet weak var detectionResultLabel: UILabel!
    
    var gradient = CAGradientLayer()
    var tapCount = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        gradient.frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY, width: self.view.frame.size.width, height: self.view.frame.size.height)
        
        let tapDetection = UITapGestureRecognizer(target: self, action: #selector(screenTap))
        view.addGestureRecognizer(tapDetection)
        
    }

    @objc func screenTap(){
        
        tapCount += 1
        detectionResultLabel.text = "\(tapCount)回、画面をタップしました"
        
        gradient.colors = [

                        UIColor(red: CGFloat.random(in: 0...255) / 255,
                                green:CGFloat.random(in:0...255) / 255,
                                blue: CGFloat.random(in: 0...255) / 255,
                                alpha: CGFloat.random(in: 0.0...1.0)).cgColor,
                        UIColor(red: CGFloat.random(in: 0...255) / 255,
                                green:CGFloat.random(in: 0...255) / 255,
                                blue: CGFloat.random(in: 0...255) / 255,
                                alpha: CGFloat.random(in: 0.0...1.0)).cgColor
                    ]

                    gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
                    gradient.endPoint = CGPoint(x: 0.5, y: 0)
                    self.view.layer.insertSublayer(gradient, at: 0)    
    }

}
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
tcpdump よく使いそうなコマンドメモ


# 環境

- Ubuntu Linux 20.04
- tcpdump version 4.9.3

# インストール例

```
sudo apt install -y tcpdump
```

# リスト

| コマンド                                  | 意味                                       |
| ------------------------------------- | ---------------------------------------- |
| tcpdump host 10.0.0.160               | IPアドレス                                   |
| tcpdump src 10.0.0.160                | 送信元IPアドレス                                |
| tcpdump dst 10.0.0.160                | 送信先IPアドレス                                |
| tcpdump port 3389                     | ポート番号                                    |
| tcpdump dst port 1025                 | 送信先ポート番号                                 |
| tcpdump portrange 21-23               | ポート番号の範囲指定                                |
| tcpdump tcp                           | プロトコル指定TCP                               |
| tcpdump udp                           | プロトコル指定UDP                               |
| tcpdump icmp                          | プロトコル指定ICMP                              |
| tcpdump host 10.0.0.160 and tcp       | AND の使い方例                                |
| tcpdump host 10.0.0.160 or 10.0.0.161 | OR の使い方例                                 |
| tcpdump -c 1                          | 1回だけ                                  |
| tcpdump -X                            | HEX形式で出力                                 |
| tcpdump -X -c 1 icmp                  | 組み合わせ例（1回のICMPをHEX形式で）                   |
| tcpdump port 80 -w capture\_file      | PCAP (PEE-cap)形式でファイル出力、Wiresharkで読み込み可能 |
| tcpdump -i eth0                       | インターフェース指定                               |
| tcpdump -D                            | インターフェース一覧取得                             |


# ICMPを1回キャプチャした例

![icmp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083912/e8c3dcde-b108-33e1-489c-bdcdfa24e72d.gif)

# 参考サイト

https://danielmiessler.com/study/tcpdump/
【詰まったログ】JS reduce( )でエラー

#やりたいこと
各配列の数値をそれぞれ合計したい

```
data:[
	   []
	   [300000, 600000]
	   []
	   [100007, 99999]
]
```




#エラー内容
下記で`Console.log(total)`するとエラーになる

```JavaScript
let total = data.map((val) =>
    val.reduce((sum, i) => sum + i)
  );
```

#原因
初期値（initialValue）を設定していなかったので、配列がカラ（合計するものがない）ときにエラーが出たようです。
参照：[Array.prototype.reduce()](https://www.notion.so/Reduce-87241be5e4a2453eb09f823dad4fa6db#49776fff79d24f92aa7708f5a910c71b)

>オブジェクトの配列に含まれた値の合計値を出すには、すべての項目を関数内で取得できるようにするために initialValue を指定する必要があります。



#解決策
```JavaScript
let total = beneficiariesData.map((val) =>
    val.reduce((sum, i) => sum + i, 0)
  );
```
結果

```
	   []
	   [900000]
	   []
	   [110,006]
```

末尾に初期値として0を設定すると合計できました
リモートリポジトリを複数設定したい

リモートリポジトリを複数設定する要件があったので、調べた結果を自分用に記録します。

## 現在のリポジトリを確認
```
git remote -v
origin	git@github.com:foobar/hoge-app.git (fetch)
origin	git@github.com:foobar/hoge-app.git (push)
```
ここで出力されるのが、現在登録されているリポジトリです。
2つで1セットですね。

## 追加
どこでもいいので、新たにリモートリポジトリを作成し、以下を実行。
今回はgithubで作成しました。

```
git remote add hugahuga git@github.com:foobar/hoge-app2.git
```

`hugahuga`の部分は自分で好きなわかりやすい名前をつけます。

## 確認

最初に実行したコマンドで設定が出来ているか確認します。

```
git remote -v
origin	git@github.com:foobar/hoge-app.git (fetch)
origin	git@github.com:foobar/hoge-app.git (push)
hugahuga	git@github.com:foobar/hoge-app2.git (fetch)
hugahuga	git@github.com:foobar/hoge-app2.git (push)
```

増えていれば成功です。

## 扱い方

それぞれのリポジトリに違うタイミングで別々にpushすることが出来ます。

```
git push origin main
git push hugahuga main 
```

## 参考記事
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%81%A7%E3%81%AE%E4%BD%9C%E6%A5%AD
[Java基礎⑥]配列　複数行を配列に格納/配列をランダム出力　split・hasNextLineメソッド

<h2>初めに</h2>
前回はJavaの基本的な配列を学習しましたが、
今回は応用編です。
決まった文字で区切って配列に格納する　split　と、
複数行を読み込むhasNextLineメソッドを学習しました。

<h2>split カンマで分割して配列に格納する</h2>

```java:
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String data = sc.nextLine();
        String[] array = data.split(",");
        System.out.println(array[0]);
    }
}
```

標準入力で、「ごはん,おかか,梅干し」と打つと、「ごはん」が出力されます。

以下を追記すると、配列の中身を一つずつ出力できます。

<h4>配列の中身を取り出す</h4>

```java:
for (String lunch : array){
System.out.println(lunch + "を食べた");
}
```

<h2>複数行データ→配列に格納</h2>

<h3>まずは複数行のデータを読み込む</h3>

```java:
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
       //行データがある間繰り返すという記述
        while (sc.hasNextLine()) {
            String data = sc.nextLine();
            System.out.println(data);
        }
    }
}
```

このように書けば、行を増やしても増やしても表示されます。
```hasNextLine()```メソッドは、
入力されてる行がまだあるかどうかを確認するメソッドです。

<h3>配列に格納し、拡張for文で出力</h3>

```java:
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
//データの数がわからないのでArrayListを用意する
        ArrayList<String> array = new ArrayList<String>();

        while (sc.hasNextLine()) {
//データが存在する間、dataに格納する
            String data = sc.nextLine();
//dataをarrayにaddする　= 配列に格納する
            array.add(data);
        }
//ここからは拡張for文の出番。
        for(String str : array) {
            System.out.println(str);
        }
    }
}
```

<h2>難：カンマ区切りの複数行データを配列に格納し出力</h2>

カンマ区切りのデータが複数行あり、
「りんごを５個買った」「レモンを３個買った」というように出力したい。

標準入力の内容
りんご,５
レモン,3
メロン,5


```java:
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
//行がある限り処理を繰り返す
        while (sc.hasNextLine()) {
            String line = sc.nextLine();
            String[] fruit = line.split(",");
            System.out.println(fruit[0] + "を" + fruit[1] + "個買った");
        }
    }
}
```

<h2>難　配列の中身をランダムで出力</h2>

以下はじゃんけんプログラムです。
グー,チョキ,パー　という標準入力からランダムに出力します。

```java:
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 標準入力から1行取得 グー,チョキ,パー
        Scanner sc = new Scanner(System.in);
        String data = sc.nextLine();
        String[] array = data.split(",");
// rand変数に、配列の長さの数字をランダムに入れる
        double rand = Math.random()*array.length;
//num変数にint型にしたrandを入れる
        int num = (int)rand;
// ランダムに選んだ配列の要素を出力
        System.out.println(array[num]);
    }
}
```



<h2>終わり</h2>
AWS LambdaでサクッとAPIを叩きたい

#AWS マネジメントコンソール上でLambdaを実装して、APIを叩きたい
サクッとWEBAPIをLambdaで叩きたい人向けです。
AWSのコンソール上のコードエディターのみで作業を完結させたいときに。

##こんな人向け
・WEBAPIを実行したい
・AWSマネジメントコンソールのみで作業を完結させたい
・headerに認証キーを付けたい
・認証キーは環境変数に入れておきたい
・返り値はステータスコードだけ取れればよい

##環境情報
AWS Lambda

 - ランタイム：Python3.9


##ソースコード（PUT API）
Lambda 標準の同包モジュールのみでの実装するため、
AWS Lambda コードエディター上に下記を張り付けるだけです。

```python
import os
import json
import urllib.request
    
def lambda_handler(event, context):
    
    #PUT API
    url_str = "https://APIURL/"
    headers = {"Authorization" : os.environ.get('BearerToken')}
    data = "data"
    request = urllib.request.Request(url_str, data.encode('utf-8'), method='PUT', headers=headers)
    response = urllib.request.urlopen(request)
    res_code = response.getcode()
    
    # PRINT STATUS CODE
    print(res_code)    
    return {
        'statusCode': res_code
    }

```

##環境変数の設定
AWS Lambda上、「**設定**」タブ内にある「**環境変数**」を設定しましょう。
環境変数の名称は、ソースコードの**"BearerToken"**です。


##出会ったエラー
```text
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
```
**dataはstr型ではなくbytes型である必要があります。**
スタックオーバーフローで同じエラーを抱えている人に多く出会いました。
結論としてはdataをエンコードしてあげる必要があります。

##おわりに
ちょっと確認したいだけだから5分でできると思ったら15分掛かったので記事にしました。
久しぶりのpythonは、アレっとなりますね。
開発初期の検証などに。
バリデーションとは？

昨日の学習の復習です！

#バリデーション、、

クライアントが入力した情報（データ）をデータベースに保存するときに、制約をかけること！（バリアを張ることって自分は覚えています）

例えば
名前とメールが空（入力されてない）だと登録できませんよー
何文字以内にしてね！
数字しか許さん　　　などなど

#####そこで使われるのが、、、

##validatesメソッド!!!
バリデーションを設定する時に使用するメソッド

こんな風にバリデーション（バリア）します

```
validates :カラム名, バリデーションの種類
```

１つ例として

```
validates :name, presence: true
```

バリデーションの種類でpresence: trueと書くことでnameカラムが空だと登録できませんよーというバリデーションを制約（バリア）をかけている 

以上！
Terraform tfstateのproviderを更新する

## はじめに

Terraform v0.12.29で作成したリソースを更新しようとしたところ、
リモートのstateファイルのproviderが更新できず解決に四苦八苦したため、
解決方法を残します。

## 実行環境

- macOS Big Sur 11.4
- Terraform v0.14.3

## 経緯

半年ほど前にterraformで作成したAWSリソースを更新する機会があったのですが、
いざtfファイルを変更して`terraform plan`を実行したところ

```
Error: Could not load plugin


Plugin reinitialization required. Please run "terraform init".

Plugins are external binaries that Terraform uses to access and manipulate
resources. The configuration provided requires plugins which can't be located,
don't satisfy the version constraints, or are otherwise incompatible.

Terraform automatically discovers provider requirements from your
configuration, including providers used in child modules. To see the
requirements and constraints, run "terraform providers".
```

プラグインが読み込めないとエラーが出ました。

`terraform init`を再実行しろと言われているので実行したところ

```
Error: Invalid legacy provider address

This configuration or its associated state refers to the unqualified provider
"archive".

You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.


Error: Invalid legacy provider address

This configuration or its associated state refers to the unqualified provider
"aws".

You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.
```

またもやエラーが（providerにawsと、Lambdaのzip用にarchiveを利用していました）。
Terraform 0.13 にアップグレードしろと言われているものの、実行時のバージョンは0.14.3です。

stateファイルはS3で管理していたので、とりあえず.terraformディレクトリを削除して
再度`terraform init`してみましたが、結果は変わらず。

そこでS3に保存しているtfstateを確認したところ、`"terraform_version": "0.12.29"`となっていました。
なるほどリモートのstateファイルが更新できていなかったようです。

## 解決方法

どうやらv0.13からproviderの送信元アドレスの指定方法が変更されたらしいので、
以下のコマンドでstateファイルのproviderを更新しました。

```zsh
terraform state replace-provider registry.terraform.io/-/aws hashicorp/aws
```

```zsh
terraform state replace-provider registry.terraform.io/-/archive hashicorp/archive
```

その後`terraform init`で無事terraformのバージョンも更新でき、
`terraform apply`も実行できました！

## 最後に

どうやらv0.12.29からv0.13にアップグレードするときに踏まないといけない手順だったようで、
[公式][terraform]のv0.13アップグレードガイドにしっかり書いてましたね、、、

余談ですが、v0.13にアップグレードしたことでtfファイルを変更していないのに差分が出るリソースもあるみたいなので、
意図しない変更が加わっていないか注意しておきましょう。

[terraform]: https://www.terraform.io/upgrade-guides/0-13.html
AWS KMS セキュリティ RDSとS3を暗号化


#キーの作成
AWS KMSコンソール＞カスタマー管理型のキー＞キーの作成
キーのタイプ：対称
詳細オプションはデフォルトのまま
エイリアス：キーの名前になるためわかりやすいものにする(Application1-keyなど)
管理できるユーザーと使用できるユーザーをチェック

#キーを使って暗号化する
作成したキー名をクリックする
ARNの文字列をコピーしておく

##RDSを暗号化する
データベースの作成をする際に以下項目を設定

###追加設定
AWS KMS キー：キーのARNを入力
ARN：コピーしたものをペーストで作成したキーを選択する

##スナップショットを暗号化する
暗号化したいスナップショットのコピーを作成する際に以下項目を設定
スナップショットをチッェク＞アクション＞スナップショットをコピー

AWS KMS キー：キーのARNを入力
ARN：コピーしたものをペーストで作成したキーを選択する
API開発に役立つCharlesについて

## Charlesの概要
Charlesは、PC上で動作するWebプロキシ（HTTP Proxy / HTTP Monitor）で、WebブラウザまたはアプリケーションをCharlesを介してインターネットにアクセスするように設定すれば、送受信されるデータを表示することができます。

送受信データは、リクエスト、レスポンス、HTTPヘッダー（クッキーやキャッシュ情報を含む）などが対象となります。

## Charlesを使う背景
API開発をする際、通信の中身を確認したいことはよくあります。

例えばAPIの不具合確認などで、状況を再現して、APIのレスポンスの確認をしたい。といった場合、Charlesを使って実機で状況を再現して送受信される通信の中身を確認すると、手軽に確認作業が行えて便利です。

## インストール
公式サイトからインストールしてください。
https://www.charlesproxy.com/latest-release/download.do

### 備考
Charlesはシェアウェアで、試用版を30日間無料で使用できます。
無料期間経過後は、試用版として、継続使用30分間の制限付きで使用することができます。30分経過後にアプリケーションが終了しますが、引き続き使用したい場合、Charlesを再起動すれば使用できます。

有料版は5,000円/1ライセンスほどで購入できます。
ですが、自分は試用版で十分使用できているため、有料版は購入しておりません。
https://www.charlesproxy.com/buy/

## Charles側の設定
### ポート番号の設定（初回設定時のみ必要）
Charlesを起動したら、ツールバーから Proxy > Proxy Settings... を開いて、使用するポート番号等の設定を行います。
デフォルトのポート番号が8888となっていますが、既に使用されているポート番号の場合、よしなに変更して設定してください。
自分は7777にしています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116234/312fc059-77db-eb74-6272-22376df6bede.png" width="640px">

### プロキシに必要なPCのローカルIPアドレスを取得
Charlesのツールバーから Help > Local IP Address を開いてローカルIPアドレスを取得します。

### SSLプロキシ設定（初回設定時のみ必要）
Charlesのツールバーから Proxy > SSL Proxying Settings... を開いてEnable SSL Proxingのチェックボックスを有効にします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116234/809fefd4-e459-5565-535d-03624aa7b06a.png" width="640px">

### SSL証明書の設定（初回設定時のみ必要）
Charlesのルート証明書は、信頼できるルート証明書のリストに含まれていないため、その証明書を受信するとアプリケーションに警告が表示されます。

Charlesのルート証明書を信頼することで証明書の警告が表示されないようになります。

手順の説明は公式サイトに預けます。
https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/

## 通信を確認したい端末側の設定
今回の場合iOS端末の通信の中身を確認したかったため設定の説明はiOSの前提とします。

設定 > Wi-Fi を開いて、接続しているWi-FiのHTTPプロキシのプロキシを構成を「手動」にします。

Charles側の設定で設定、取得したポート番号、ローカルIPアドレスを入力してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116234/b0d4a986-a6cd-0a1d-3151-9e7e5b024d69.png" width="640px">

これでiOSの通信を確認することができます。

## 注意事項
最後に注意事項ですが、利用規約でリバースエンジニアリングを禁止する旨を明記しているアプリケーションに対しては、解析を行わないようにしてください。
自サービスの開発に役立てる目的で使うことを推奨します。

## 参考文献
- [通信系のデバッグには Charles が便利](https://qiita.com/usagimaru/items/d340e87da98e62f99b60)
- [【開発支援ツール】Charlesの使い方【神ツール】](https://qiita.com/ishigaki_hige/items/41ab31b002c8649be2c2)
- [Charles Proxy を利用したパケット情報の収集方法（Mac OS）](https://helpx.adobe.com/jp/x-productkb/global/how-to-get-packet-information-with-charles-on-mac-os-jp.html)
Cloud data fusionのインスタンス立ち上げ

## これは何

Cloud data fusionの導入までを描いたメモです。
実際にデータを移行させたわけではなく、立ち上げのみです。

## Cloud data fusionとは

![studio-deploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/0ffa433a-6851-9c57-62f2-ab3567554dad.png)

クラウドデータをあらゆる規模で統合するためのツールです。
コード等を意識せず、マウスだけで視覚的に操作できるインターフェースによって、ETL(Extract/Transform/Load)パイプラインをデプロイ可能です。


## Cloud data fusionインスタンス立ち上げ

リージョンをasiaではなく、us-とかにすると、HUBの立ち上げに恐ろしく時間がかかったので、asiaにしました。
最新版だとサービスアカウントのところで、権限エラーが発生。

![スクリーンショット 2021-09-09 14.16.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/9b49cf36-e7c9-71f6-613d-9b657053e69d.png)

![スクリーンショット 2021-09-09 14.16.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/b362c55b-5fa7-8c4f-fb96-e8040d1fa3cd.png)

![スクリーンショット 2021-09-09 14.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/fba7cdf3-b7f0-69e2-d40e-03f2eebf9601.png)

今回はテスト的な導入で使いたいだけで、最新版である必要がないのでバージョンを**6.1.4**にします。
作成に20分くらいかかります。

インスタンスを表示を押下します。

![スクリーンショット 2021-09-09 14.36.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/dcfae017-07f1-7251-f405-ef70e71447bf.png)

Studioを押下

![スクリーンショット 2021-09-09 14.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/ce1d697b-13b3-7e5e-0776-4b14f9b574df.png)

## 総括

インスタンスの立ち上げは成功しました。
今回はETLパイプラインを作成してはいませんが、作成したらまたまとめます。

なお、Google Cloud が提供してくれている、以下の小さなサンプル データセットをローカルマシンにダウンロードして、パイプラインを作ることもできます。

**配送データのクレンジング**
https://cloud.google.com/data-fusion/docs/tutorials/sample_datasets/shipment-data-cleansing-cdap-data-pipeline.json?hl=ja
**米国での配送遅延**
https://cloud.google.com/data-fusion/docs/tutorials/sample_datasets/delayed-shipments-us-cdap-data-pipeline.json?hl=ja


## 参考

```
https://cloud.google.com/iam/docs/understanding-service-accounts?hl=ja
https://cloud.google.com/data-fusion?hl=ja
https://cloud.google.com/data-fusion/docs/tutorials/lineage?hl=ja
https://qiita.com/t-yotsu/items/5d3d36847fbc71b72b76
```
Reactメモ　memo、useMemo、useCallback 　＊個人メモ用

Reactの勉強をしている私の個人メモなので、
記事としてはわかりづらくなっています。
FBは歓迎しておりますが、温かい目で見守って頂けると幸いです。

再レンダリングの最適化：

memo　（コンポーネントの最適化）

useMemo　（変数の最適化）

useCallback　（関数の最適化）

以上
【JavaScript】関数の引数について

#はじめに
こんにちは。
JavaScriptの引数の定義についてアウトプットしていきます！

##引数とは
>引数とは、関数やメソッド、サブルーチンを呼び出す際に渡す値のことです。プログラム言語では、この「渡された値に対して処理を行い、結果を返す」ということを行っています。

> 参照：https://job-support.ne.jp/blog/javascript/basic-argument

```javascript:JavaScript
//function 関数名(引数1, 引数2,~)
function fn(a,b){
  return a * b
}

//関数名(引数1, 引数2,~)
fn(3,4);  //12
```
関数`fn`の第１引数に`a`を、第２引数に`b`を記述する。関数を呼び出す際、引数に値や式を記述したものが関数内で実行されるので、`a`と`b`の積が出力される。
<br>
<br>

```javascript:JavaScript
function fn(name,jobs){
  console.log(`${name}は、${jobs}になる。`)
}
```
```javascript:JavaScript
fn('佐藤','エンジニア');         //佐藤は、エンジニアになる。

fn('エラー');              //エラーは、undefinedになる。

fn('山田','マーケター',20);  //山田は、マーケターになる。
```
関数を呼び出すときの引数が少ない場合、第２引数を参照すると`undefined`となる。それとは反対に、呼び出す時の引数が多い場合は、第３引数（20）が使用されないだけで、表示は可能となる。


<br>



#最後に
ここまで引数についてまとめました。
関数とセットでなんとなく使用していたのですが、新しい発見があって以前よりも理解が深まりました。
これからもアウトプットしながら学習を進めていきます！
急にpip installで一部のライブラリのインストールが失敗するようになった件

# はじめに
この記事は2021年9月6日以降に、
pipでのインストールで以下の様なエラーが出て困っている人に向けて書いています。
（私の場合、GDALのインストールが失敗するようになりました）

```
Collecting GDAL==2.2.3
  Using cached GDAL-2.2.3.tar.gz (475 kB)
    ERROR: Command errored out with exit status 1:

（～中略～）

    Complete output (5 lines):
    /usr/lib/python3.7/distutils/dist.py:274: UserWarning: Unknown distribution option: 'use_2to3_fixers'
      warnings.warn(msg)
    /usr/lib/python3.7/distutils/dist.py:274: UserWarning: Unknown distribution option: 'use_2to3_exclude_fixers'
      warnings.warn(msg)
    error in GDAL setup command: use_2to3 is invalid.
    ----------------------------------------
WARNING: Discarding https://files.pythonhosted.org/packages/fb/62/e4c597c0b52bf0ddf7073c57e998c96cd98a8281a2cf40a8c036b34e4ec0/GDAL-2.2.3.tar.gz#sha256=561a952394bc1d9291179a8677eb6f5dafbf3e361c851f3dbb59db604c9b8e8b (from https://pypi.org/simple/gdal/). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
ERROR: Could not find a version that satisfies the requirement GDAL==2.2.3 (from versions: 1.5.0, 1.5.2, 1.6.0, 1.6.1, 1.7.0, 1.7.1, 1.8.1, 1.9.0, 1.9.1, 1.10.0, 1.11.0, 1.11.1, 1.11.2, 2.0.0, 2.0.1, 2.1.0, 2.1.3, 2.2.0, 2.2.1, 2.2.2, 2.2.3, 2.2.4, 2.3.0, 2.3.1, 2.3.2, 2.3.3, 2.4.0, 2.4.2, 2.4.3, 2.4.4, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.2.0, 3.2.1, 3.2.2, 3.2.3, 3.3.0, 3.3.1, 3.3.2)
ERROR: No matching distribution found for GDAL==2.2.3
```

# サクッと結論
### 原因
GDALに限らず、
以下のようなエラーメッセージであれば、setuptoolsが原因である可能性が高いです。

```
error in 〇〇 setup command: use_2to3 is invalid.
（〇〇はインストール失敗したライブラリ名）
```

setuptoolsはv58.0.0以降、"use_2to3"が失敗するようになっています。
（"2to3"はpython2系を3系に変換するやつらしい。詳しくは知らんけど。）

以下、[setuptools公式ドキュメント](https://setuptools.readthedocs.io/en/latest/history.html#history)にて
v58.0.0の説明欄に「"2to3"はもうサポートしないよ」と書かれています。

### 対応方法
v58.0.0より古いverにダウングレードすれば、解決します。

setuptoolsのverを下げたい場合は、pipで58.0.0より古いverを指定して
installすれば下げられます。

```
（以下は57.4.0を指定した例）
pip install setuptools==57.4.0
```

# おわりに
twitterで調べた限りGDAL以外でも起きるようなのですが、
あまり情報が出回ってなさそうだったので、記事にしておきました。

ちなみに今回の解決に至ったのも、twitterで"use_2to3"について
呟いている方々がおられたおかげです。

twitterで色々情報出してくれるエンジニアの方々に
この場を借りてお礼申し上げます。
AWS ECS Task実行時にエラー CannotPullContainerError


# エラー内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/779920e7-9a92-6a43-34db-c27419fd9b5b.png)


> CannotPullContainerError: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) 

# 解決策

タスク実行時にPublicIPを付与する

```tf
resource "aws_cloudwatch_event_target" "example_batch" {
  target_id = "example-batch"
  rule      = aws_cloudwatch_event_rule.example_batch.name
  role_arn  = module.ecs_events_role.iam_role_arn
  arn       = aws_ecs_cluster.example.arn

  ecs_target {
    launch_type         = "FARGATE"
    task_count          = 1
    platform_version    = "1.3.0"
    # ターゲットをarnで設定
    task_definition_arn = aws_ecs_task_definition.example_batch.arn

    network_configuration {
      assign_public_ip = "true" ★
      subnets          = [aws_subnet.public_subnet_1a.id]
    }
  }
}
```

private subnetで使いたいならNATゲートウェイを使う
OpenWrtでds-lite接続

# OpenWrtを使用したds-lite接続

transix IPv4接続とか クロスパス と呼ばれる楽天ひかり等で使われているds-liteの設定メモ書きです。

設定には一旦インターネット環境が必要です。

公式にもサラッと書かれています。
[IPv4/IPv6 Transition Technologies](https://openwrt.org/docs/guide-user/network/ipv6_ipv4_transitioning#dual-stack_lite_tunnel_ds-lite_ipv4_in_ipv6)

## OpenWrtのインストール

インストール手順周りは機種いっぱいあるので割愛
最低限インターネット利用できるように設置します。（一旦PPPoE設定や別ルータにWAN繋ぐなど）

### ds-liteパッケージのインストール

OpenWrtのSystemからSoftwareへ移動しUpdate listsでまずはパッケージリストの更新。

ds-liteパッケージ探してインストールする。（これがデフォルトで含まれてないので面倒）

ついでにluci-i18n-base-jaを入れておくとリロードで画面が日本語になります。

インストール後は一旦再起動。

### ds-liteの設定

ネットワークのインターフェースに進みWANの設定を編集。
Dual-Stack Lite(RFC6333)に変更をしてプロトコルを切り替えAFTRを入力。

transix（gw.transix.jp）
クロスパス（dgw.xpass.jp）

編集が終わったら右下の保存ボタン。

WANのIPアドレスが正しく表示されたら完了です。

### 補足

AFTRアドレスが名前ではうまく行かない場合があるので、WANがつながらない場合IP直打ちします。

transix（gw.transix.jp）地域によってどれか使用
東日本 2404:8e00::feed:100 2404:8e00::feed:101
西日本 2404:8e01::feed:100 2404:8e01::feed:101

クロスパス（dgw.xpass.jp）
2001:f60:0:200::1:1
git submodule updateで進捗状況を表示する

## 問題

`git submodule update` コマンド使用時に、対象の外部サブリポジトリの容量が大きい場合、何も画面表示が変わらないまま固まってしまう（ように見えてしまう）

## 解決方法

`--progress` オプションを付与することで、通常の `git clone` 時と同様に進捗状況が表示されるようになる。

```
$ git submodule update --progress
...
remote: Counting objects: 16355, done.        
remote: Compressing objects: 100% (10388/10388), done.        
remote: Total 16355 (delta 9044), reused 18163 (delta 8150)        
Receiving objects: 100% (16355/16355), 197.16 MiB | 1.02 MiB/s, done.
```

## 備考

Git 2.11より `git submodule update` の `--progress` オプションが追加されている。
https://github.com/git/git/commit/72c5f88311dab7149fcca1f6029414ccb776fee8
Laravel JetStream PWリセット時にメールアドレス入力を除外したい。


JetStreamでPWリセットする際にメールアドレスを入力せずに
変更するのどうしたらいいのかな？と思いました。

## パッと考えたこと
- メール送信時にCookie を設定して、PW変更画面で読み取って表示
- 送信するトークンにメールアドレスを追加してControllerなどでうまく処理する。

## 結論
送信されるリセットメールのurlパラメータ見てませんでした。

`http://localhost:8080/reset-password/{トークン}?email=ogaki.kana%40example.net`

`auth/reset-password.blade.php`で使用されている
input typeを変更するだけでした。

``` php
<x-jet-input id="email" class="block mt-1 w-full" type="hidden" name="email" :value="old('email', $request->email)" required autofocus />
// typeをhiddenに変更
<x-jet-input id="email" class="block mt-1 w-full" type="hidden" name="email" :value="old('email', $request->email)" required autofocus />

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318237/af9a6ed3-1ca8-1e52-b65b-2c61956fa915.png)
パスワード変更できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318237/9226bdfd-50cc-79b6-d966-cb24fde2d041.png)

後は、自動でログインできれば、ユーザーにとっていいかな。
【GCP】総合提案書に使えそうなドキュメント

コストパフォーマンス
https://cloud.google.com/pricing?hl=ja
https://cloud.google.com/compute?hl=ja　カスタムマシンタイプの部分

インフラ
https://cloud.google.com/infrastructure?hl=ja

グローバルネットワーク
https://cloud.google.com/about/locations?hl=ja#regions
https://cloud.google.com/about/locations?hl=ja#network

BQについて
https://cloud.google.com/bigquery?hl=ja

セキュリティ
https://cloud.google.com/security?hl=ja
https://cloud.google.com/security/infrastructure?hl=ja
https://cloud.google.com/blog/ja/products/gcp/titan-in-depth-security-in-plaintext
https://cloud.google.com/titan-security-key?hl=ja


カーボンニュートラル
https://cloud.google.com/sustainability?hl=ja
ターミナルでActionView::Template::Error


今日、初歩的なミスでずっと引っかかってしまいました:frowning2:


エラー内容
---

`NoMethodError undefined method
 errors' for nil:NilClass``



↓ターミナル

```
ActionView::Template::Error (undefined method `errors' for nil:NilClass):
    1: <% if model.errors.any? %

　　　　　　 2: <div class="error-alert">
    3: <ul>
    4: <% model.errors.full_messages.each do |message| %>
  
```


 nil:NilClassから、『クラスがないよ！』
undefined method から『メソッドが未定義なんだが、、、』
というエラーということが考えられます。


原因
-----

　　


```ruby:views/new.html.erd
 </header>
  <div class="items-sell-main">
    <h2 class="items-sell-title"> 商品の情報を入力 </h2>

    <%= form_with model:@items, local: true do |f| %>
    <%= render 'shared/error_messages', model: f.object %>

````


```ruby:controllers/items_controller.rb
 def new
   @item = Item.new
 end

````


コントローラーとビューファイルの記述を見ると、
コントローラーは＠itemと定義
ビューファイルは＠itemsと定義

ここの部分を＠itemに統一して、直したら解消されました。
コントローラーに合わせてビューファイルを＠itemに変更するだけでした。


:frowning2::frowning2::frowning2:
Expo で iPadOSアプリ の作成


#環境設定

```terminal:環境設定
$ npm install expo-cli --global
```

```terminal:プロジェクト作成
expo init myAPP
cd myApp
```

####起動
```terminal:myApp
yarn start
```

####BootStrap
```terminal:myApp
expo init myAPP
cd myApp
yarn start
```
【CSS】比率で配置できるFlexboxのflexプロパティ

# はじめに
* 比率で配置できるFlexboxのflexプロパティについてのまとめです。

## ```flex:数値``` 比率で配置する
* アイテムをどのような比率で配置するか

```html:html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body style="margin: 0">
    <div class="container">
      <div class="item item1">Item 1</div>
      <div class="item item2">Item 2</div>
    </div>
  </body>
</html>
```

下記のコードの場合、１対３の比率で配置できる

```css:css
.container{
  display: flex;
}

.item1 {
  background-color: pink;
  flex: 1;
}

.item2 {
  background-color: blue;
  flex: 3;
}
```
|![FireShot Capture 075 - Document - .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95954/54c495cd-01a9-1d46-648e-910cab1c2a2c.png)|
|:-:|