OmniAICreator/Qiita-1.07M huggingface dataset:
WPでアーカイブページ（日付、投稿者)がトップにリダイレクトしてしまった時にCHECKした項目

# WPでアーカイブページ（日付、投稿者)がトップにリダイレクトしてしまった時にCHECKした項目

運用中のWordpressで日付、投稿者のアーカイブページを使用しようとしたら、トップへのリダイレクトがかかっていて困理ました。
その時に確認した項目を備忘録的に記載しておきます。

## .htaccessを疑う
セキュリティー強化の一環でarthor/hogeに遷移した時にトップにリダイレクト設定したような気がしたのでまず.htaccessを疑った。
DocumentRootの.htaccessにこんな記述がないかチェック。

```bash:.htaaccess
RewriteRule ^author/(.*)? / [R=302,L]
```
apacheでリライト設定してる場合はapacheの設定側も見た方がいいかも。

## templateのfunction.phpを疑う
上記、理由でここでリダイレクト設定したかもしれないので確認。
こんな記述がないかチェック

```php:functionp.php
function disable_author_archive() {
	if( is_author() ){
		wp_redirect( home_url() );
		exit;
	}
}
add_action('init', 'disable_author_archive');
```
投稿者アーカイブへのリクエストだったらトップに遷移みたいな記述がなければOK。

function.php以外のファイルで設定している可能性も考慮して、
`is_author()`やら`wp_redirect( home_url()`やらでgrepして確認しました。

## プラグインを疑う
結局、上記のどれでもなかったので、ローカル環境に運用中のWPをセットアップしてプラグインを一個ずつディアクティブして確認しました。
結果、YaostSEOの設定が原因でした。

YaostSEOのSetteings -> Other -> Archive indexがDisableになっていることが原因でリダイレクト。
開設当時は一人でしか記事書かないからAuthorいらんわーって思ってIndex Desableにしてたんやった。

この原因を特定するのに半日使ったので、もし同じように悩んでこれが原因な人のお役にたてたら幸いです。
深層学習トラブルシューティング

# 記事概要
深層学習 (機械学習) がうまくいかない時あるある備忘録です。

本記事では深層学習がうまくいかない原因を以下の2通りに場合わけして考えます。

1. モデルパラメータがうまいこと獲得されないケース
2. モデルパラメータは獲得されるけどそれ以外の部分 (前処理や後処理) でミスっているケース

ツッコミ歓迎です。そのうち加筆するかもです。

# モデルパラメータがうまいこと獲得されないケース
## ハイパーパラメータ編
### 学習率が大きすぎる/小さすぎる
深層学習において学習率の設定はめちゃくちゃ重要です。200エポックかけて到達したロスに、学習率を変えたら10イテレーションで到達した❗️みたいなことがザラにおきます (おきました) 。論文の再現をしたい時には著者の使っている学習率を使うのが丸いです。僕の場合は次のような順序で探索してそれっぽいパラメタを見つけることが多いです。

1. 著者のリポジトリで使われているパラメタ
2. 論文に書いてあるパラメタ
3. その他再現実装のパラメタ
4. 類似モデルで使われているパラメタ
5. 気合で神パラメタを引く (grid search / [optuna](https://optuna.org/))

ちなみに学習率とバッチサイズには関係があり、(例えば https://arxiv.org/pdf/1711.00489.pdf など) バッチサイズを n 倍した場合、学習率も n 倍する必要があります。論文のバッチサイズは GPU クラスタを使用することを前提にしていることも多々あるので、GPU 1台で細々と学習するときはバッチサイズに加えて学習率を調整することをお忘れなく。 

## データ編
### GT の生成をミスる
クラス分類程度なら GT (ground truth / 正解データ) を作る必要はないですが、物体検出などやや入り組んだことをやろうとすると GT の作成をミスることが往々にしてあります。例えば CenterNet (https://arxiv.org/abs/1904.07850) だと、(中心座標、幅、オフセット) のテンソルを GT として作ってやる必要があるのですが、まあ盛大なバグを埋め込むことに成功しました。生成した GT はちゃんと目視確認しましょう。

# 前処理や後処理でミスっているケース (モデルパラメータは良い)
## データ編
### 検証用データをオーグメントしてしまう
物体検出など位置が重要なアルゴリズムはクリティカルになることがあります。後処理コードがオーグメントしない前提で書かれているにもかかわらず、入力がオーグメントされている場合などですね。まあまあ酷いことが起きます。後処理がオーグメントを考慮できるようにしてあるにしても、一般にオーグメントするとモデルの性能は落ちますので正確な評価のためにも検証用 / テスト用データはオーグメントしないようにしましょう。

### RGB と BGR を間違える
あまりないケースではあるのですが、`PIL.Image.open` と `cv2.imread` はチャンネルが逆転しているので不幸な事故が起きることがあります。前者は `'RGB'` 、 後者は `'BGR'` です。訓練時は `cv2` で読んでテスト時は `PIL` で読むみたいな実装になっている場合問題になります。モデルに流す前に transpose する必要がありますね。平均分散を使った標準化処理をしている場合も問題がおきます。PCA color augmentation とかでも問題が起きるかな。

## モデル編
### 最後の活性化関数を忘れる
僕は普段 pytorch で実装しているのですが、テスト時に最後の活性化関数をつけ忘れることが時々あります。例えば物体認識だと `torch.nn.CrossEntropyLoss` を使うかと思うのですが、これを使ってるとテスト時に `nn.Softmax` をつけ忘れたりすることがあります。これに関しては出力のレンジを調べれば簡単にチェックできるかなという感じです。

## 後処理編
### 出力を元の空間の縮尺に戻し忘れる
物体検出なんかでやりがちなのですが、`(3, 512, 512)` の入力が `(80, 128, 128)` の出力で出てくるみたいな、空間方向に縮尺が変化するモデルを使っている時に起こります。これをやらかすと、物体検出だと GT との IoU が著しく小さくなるのでいくらモデルパラメータが正しく学習できていても mAP が地を這う現象が起きます。学習データの GT を元の空間に戻してみてきちんと元の値に戻るかをチェックしてみるといいと思います。

## 評価指標編
### そもそも評価指標が間違ってる
「学習してるのに評価値 (accuracy / mAP / MSE など) が全然上がらんぞ❗️」ということは往々にしてあります。この時ありがちなのがそもそも評価指標の実装を間違えているケース。間違え方は多種多様なので具体的にどうしろとかはないのですが、オープンソースの評価指標がある場合はそれを使った方が丸いです。実装する時も評価指標に合わせて設計するといいのかなと思います。オープンソースの評価指標はいろいろありますが、github ならスターの数が3桁以上ならまず信用していいのではないかなと思います。僕が指標探す時の優先順位は次のような感じです。

1. データセット公式
2. github のリポジトリ
3. 気合で実装

3 は本当に最終手段でなるべくやらない方がいいです。あまりにも本質的でないところに時間が取られ過ぎてしまうので…… 実装の練習をしたいとかでない限り回避した方がよい択だと思います。「どうしても自分のリポジトリで完結したいんや❗️」という人はすでにあるリポジトリをフォークしましょう。
【WordPress】メディアの画像の置き換える

## はじめに
例えば、多くの製品を扱う企業のサイトをWordPressで運営中、
製品のパッケージデザインが変わったので、画像を変更してほしいという依頼が来た時、ゴールへの道筋は幾通りか存在するかと思います。

今回、便利なプラグインで対応できたので、そちらの紹介をします。

## Enable Media Replace
導入や使用方法は参考のリンクを見ていただくとして、心配していた下記の内容が問題なかったので、使用に踏み切れましたという点を共有させていただきます。

【懸念点】画像のURLや名前が変更されてしまうのではないか。
【結果】拡張子を揃えておけば、ファイル自体を置き換えてくれるので、サイトに影響を出すことはありませんでした。試していませんが、新しいファイル名を採用してリンクの方を更新する事もできるようですが、本文中のリンクなどまで更新されるのかは不安が残ります。

![wordpress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274706/e2255f61-003f-bd39-0e04-bc52a2610a9d.png)

【懸念点】サムネイル（サイズバリエーション）まで再作成されるか。
【結果】作成されました！

## 参考 :books:
https://www.t3a.jp/blog/it-all/wordpress-change-image/
AWS IoT 概要

# AWS IoT
* [AWS IoTとは](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/what-is-aws-iot.html)

## AWS IoTコンポーネント
### [メッセージブローカー](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-message-broker.html)
* [プロトコル](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/protocols.html)

|プロトコル|認証|Port|ALPN ProtocolName|メッセージ|
|---|---|---|---|---|
|MQTT|X.509クライアント証明書|8883,443|x-amzn-mqtt-ca|subscribe, publish|
|HTTPS|X.509クライアント証明書|8443,443|x-amzn-http-ca|publish|
|HTTPS|SigV4|443|該当なし|publish|
|MQTT over WebSocket|SigV4|443|該当なし|subscribe,publish|

* ALPNによりMQTTをport443で利用可能
    * https://aws.amazon.com/jp/blogs/news/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/
    * ALPN (Application Layer Protocol Negotiation): [RFC7301](https://tools.ietf.org/html/rfc7301)
    * クライアントがALPN拡張をサポートしていることが前提
        * opensslは1.0.2以降対応 [openssl-1.0.2-notes](https://web.archive.org/web/20140904045720/http://www.openssl.org/news/openssl-1.0.2-notes.html)

* [MQTT](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/mqtt.html)
    * MQTT  version 3.1.1に基づく（下記例外）
    * 仕様からの逸脱あり
        * QoS0でメッセージが複数回(0以上)配信される場合がある。(DUPフラグ未設定)
        * Q0S2は未サポート。QoS2のリクエストはACK(PUBACK or SUBACK)を応答しない。
        * 新規subscribeに対するラストメッセージの保持(retain)はサポートされない。
            * 接続単位の永続セッション(cleanSessionフラグ)はサポート
                * [MQTT永続化セッション](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/mqtt-persistent-sessions.html)
            * willメッセージに関する制限記述は無いのでサポート
    
* [制限事項](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/limits-iot.html)

* 対応するMQTTデバイス
    * [デバイスを設定する](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/configure-iot.html)
        * 専用デバイスだけでなく、MQTTクライアントも対応と読める

### [デバイスシャドウサービス](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-device-shadows.html)
* デバイスシャドウ：デバイスの現在の状態情報の保存と取得に使用されるJSONドキュメント
* デバイスシャドウサービス：AWS IoTに接続された各デバイスのシャドウを管理するサービスで、MQTTまたはHTTPで各デバイスの状態（接続状態に関わらず）の取得設定を行うことができる。 


## 料金
* [AWS IoT Core料金](https://aws.amazon.com/jp/iot-core/pricing/)
* 以下、東京リージョン前提に記述（他のリージョンに比較して割高）

### 接続料金
* １デバイスのAWS IoT Coreへの接続時間に応じて１分単位で発生
* 0.096 USD (100万分あたり)

 
### メッセージング料金
* １デバイスとAWS IoT Coreの間で「送信された」メッセージ数により計算される。
    * publish, subscribeは送信メッセージ。ACKはメッセージに含めない。
* MQTT-keepaliveは対象外
* メッセージ数は、5KB毎に増加。(ex: 8KB -> 2メッセージ数)
* メッセージ100万件あたり
    * メッセージ10億件まで：1.20 USD
    * ~40億件まで：0,96 USD
    * 50億権以上：0.84 UDD
    

### デバイスシャドウとレジストリ
* デバイスシャドウやレジストリデータに対するアクセス、又は変更のオペレーション数によって発生
* デバイスシャドウ自体はThings登録時に規定で作成される。管理アプリケーションやAWS CLIからデバイスシャドウサービスにアクセス（Shadow ARNへのアクセス)しない限り課金は発生しない。
    * Shadow ARNはThings登録時に作成される。(ex. arn:aws:iot:ap-northeast-1:440364497558:thing/device_mosquitto_windows10)
* オペレーション数は、デバイスシャドウまたはレジストリのレコードサイズ1KB単位で計算される。
* 1.50 USD (オペレーション 100万件あたり)

### ルールエンジン
* ルールによるサービス(S3, DynamoDB, Kinesis)ルーティングで発生
* ルールがトリガーされる度に計算される。
* 0.18UDD (トリガーされたルール100万件あたり/実行されたアクション100万件あたり)
Pythonの仮想環境で開発を行う方法【メモ】


Pythonでの開発ルールを検討している際にPythonの仮想環境を構築することができる方法を知ったので自分用のメモに残します。
Pythonの仮想環境とはインストールしたモジュールやパッケージ、バージョンごとに分離された環境のことです。私は今までローカルだったり、仮想マシン上で開発を行ってきましたが、これを使えば仮想マシンを使わずともまっさらなPython環境を用意することができるようです。
venvというソフトウェアを使用してPythonの仮想環境を構築します。


#仮想環境の作成
まずはじめに仮想環境を作成します。下記のコマンドをターミナル上で実行することで簡単に仮想環境を作ることができます。このコマンドを実行すると実行したディレクトリの下に'環境の名前'というディレクトリが作成され、そこが仮想環境となります。
ただしディレクトリに入るだけでは機能せず、activate(有効化)が必要となります。

```shell:Terminal
Uesr$ python3 -m venv '環境の名前'
```


#仮想環境の有効化
実際にディレクトリに移動し下記コマンドを入力することで仮想環境を有効化することができます。
有効化すると、ターミナルの$とコンピュータ名の前に('環境の名前')がつくようになります。

```shell:Terminal
User$ cd '環境の名前'
User$ source bin/activate
('環境の名前') User$ 
```

#仮想環境の終了
仮想環境を終了するには下記コマンドを入力しましょう。これを実行すると有効化する前の表示に戻ります。

```shell:Terminal
('環境の名前') User$ deactivate
User$
```

#まとめ
Python開発の際にいろいろライブラリをインストールしたりすることが多いのですが、ローカルでやってしまうとライブラリ管理が大変になってしまうので、これからは仮想環境を積極的に使用しようと思います。
環境つくりも簡単なのでみなさんも使用してみてください。
備忘録 Azure AD に PowerShell で接続する

Azure や Office 365 の管理者の方は、指が覚えているくらいの内容かと思いますが、自分はしょっちゅう忘れてしまうので、備忘録として残しておきます。

# 準備
### Microsoft Azure Active Directory Module for Windows PowerShell のインストール
そのコンピューターから初めて PowerShell から Azure AD に接続する場合は、Microsoft Azure Active Directory Module for Windows PowerShell (日本語名: Microsoft PowerShell の Microsoft Azure Active Directory モジュール) のインストールが必要です。
この作業は、その PC では2回目以降は必要ありません。

以下のサイトからモジュールをダウンロードします。(最初は「ん？Office のダウンロードかな？」と勘違いしましたが、上の部分は広告なのでちょっとややこしいですね。)
[IT プロフェッショナル 用 Microsoft Online Services サインイン アシスタント RTW](https://www.microsoft.com/ja-jp/download/details.aspx?id=41950)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/b7a5cc12-bb9e-b561-378e-9cf5b8cfd1b1.png)

これから PowerShell を実行するコンピューターの OS が32ビットなら上の方、64ビットなら下の方を選択してダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/05b8ecac-e512-a092-0175-7c1003610b0f.png)

この後、ダウンロードした実行ファイルをクリックしてインストールします。コンピューターへの適切な管理者権限があれば特に困るところありません。

### PowerShell へのインストール
コンピューターへインストールするだけでは利用できず、PowerShell 上で機能を有効化するためのインストール作業が必要になります。
まず、インストールが必要なため、PowerShell に管理者として実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/fa9dcfaa-ac22-fedc-9cfe-a3905cb752bd.png)

以下を実行します。

```powershell
Install-Module MSOnline
```
Y を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/91554f5d-79af-c60a-a8e6-21936706fb01.png)

もう一回、Y を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/5502c474-0466-a7bf-e99b-84a0708d5e18.png)

# Azure AD への接続方法
PowerShell を開いて、以下を実行します。

```powershell
Connect-MsolService
```

これから実施する作業に必要な権限を持つアカウントでサインインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/9080fdcf-5aa2-0fce-c596-825dc4e47433.png)

PowerShell に戻った後、こんな画面になります。ちゃんと繋がったか心配になりますが、失敗するとエラーになるので、こうなっていたら成功と思ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593361/5aa28f44-cfef-8a4f-1501-f9520694d11d.png)

参考
[Microsoft PowerShell の Microsoft Azure Active Directory モジュールとの接続](https://docs.microsoft.com/ja-jp/office365/enterprise/powershell/connect-to-office-365-powershell#connect-with-the-microsoft-azure-active-directory-module-for-windows-powershell)
AWS ソリューションアーキテクトアソシエイト１5

##クラウドにおけるコスト最適化の重要性

- 仮想マシンやストレージがほとんど使われていない

・・・・約３割の仮想マシンやは実際にはあまり利用されていない状態で起動されている

- 不必要に24時間365日稼働している

・・・・稼働しなくてよい時間帯にも仮想マシンが起動している

- 適切なスペックのサイジングを割り当てていない

・・・・オーバースペックなサイズのまま仮想マシンを稼働させている

##AWSにおけるコスト最適化の指針

AWS Well-Architectedフレームワークの「コスト最適化」の柱では、コストを最小限に抑えるための指針として、以下の5つの設計原則が掲げられています。

###必要なリソースを必要なときに必要な分だけ利用する

従来のオンプレミス環境では、将来を見据えてあらかじめ想定された量の通信トラフィックを処理できるよう、余裕を持ったスペックのサーバーを購入・構築するため、初期費用がかかっていました。
一方でクラウド環境では、「必要に応じてリソースを柔軟に拡張」することができるため、最初は必要なリソースに基づいたスモールスタートな環境を構築し、将来のビジネス拡大に合わせて環境を増築することでコストを抑えることが可能です。
また、「使った分だけ課金」されるため、たとえば夜間など開発環境やテスト環境を利用していない時間帯は仮想マシンを停止するといった運用を行うことでコストを節約できます。

###全体的なコスト効果を測定する

ビジネスから生まれる効果や価値と、それに費やしたクラウドのコストの両面を測定しながら、「ビジネス価値÷コスト」が最大化するようなコスト最適化を行うことが重要です。
たとえば、AWSで利用しているサービスの単なるコスト削減によりビジネス価値が大きくなるのか、また、「AWSサービスの活用を増やす＝コストが増加する」ことで、ビジネス展開のスピードの価値が改善するのかなど、単なるコスト削減の視点ではなく。全体的なビジネス・コスト効果の視点で最適化を進めることが重要です。

###データセンター運用への投資を不要に

クラウド活用により、企業の競争力に直接影響しないデータセンター内のITインフラ構築・運用（たとえばサーバーのラッキングなど）はAWSが行うため、企業は競争力の源泉となるビジネス開発に集中することができます。

###投資効果の要因分析

AWSで利用したITリソースの使用量と、それを使った組織・チーム・プロジェクトが簡単に把握できるため、投資効果（ROI：Return on Investment）を組織ごとやチーム・プロジェクトごとなどの細かい単位に局所化して把握しながら。要因の分析、そしてコスト最適化などの改善の実施ができるようになります。

###マネージドサービス活用による所有コストの削減

たとえば電子メールやデータベースのサーバーなど、これまで自社で構築・運用していたITインフラをまるごとAWS上のマネージドサービスで代替することで、サーバー機器の保有や拡張などの所有コストが削減できます。
AWS ソリューションアーキテクトアソシエイト１１

#データの保護
##暗号化によるデータの保護
AWSに代表されるパブリッククラウドの特性上、データはインターネット経由で通信いされ、AWSが管理するデータセンターに保管されます。したがって、ユーザーとAWSの双方でデータを保護する工夫をしなければ、データの盗聴や流出、改ざんなど企業にとって甚大な被害を受けるリスクがあります。

- 通信の暗号化
ユーザーとAWSの間を通る通信経路（インターネットなど）における盗聴からデータを保護します。
具体的には、SSL/TLSなどの暗号化の仕組みをユーザーとAWSの間で導入します。
AWSでは以下に代表されるさまざまなサービスとの間で、データのアップロード・ダウンロードを保護するため、SSL/TLSによる通信の暗号化をサポートしています。

 - ELB
 - RDS
 - Amazon CloudFront (CloudFront)
 - Amazon API Gateway (API Gateway)

たとえば、ロードバランサーであるELBの配下に複数のEC2インスタンスで構成されるWebサーバーなどがある場合は、ELBがクライアントとWebサーバーの間でSSL/TLSの終端となり、暗号化処理を行います。

- 保管するデータ自体の暗号化
AWSのEBSやS３などに保管されるユーザーデータが。悪意ある第三者からアクセスされることを防ぎます。具体的には、クライアントサイドまたはサーバーサイドでのファイル暗号化などにより実現します。
また、暗号化や復号を行うには「鍵」の作成と管理も重要となります。

##データ暗号化の方式と場所
ユーザーとAWSとの間でデータのやり取りを行う場合、暗号化によるセキュリティ強化を検討します。暗号化の方式を検討する際には、「どこで暗号化するか」「鍵の管理はどこで行うか」の2つが重要です。
「どこで暗号化を行うか」という点については、以下の２つのパターンがあります。

- クライアントサイドでの暗号化（CSE：Client Side Encryption）
AWSへデータを送信・保存する前に、ユーザーの環境でデータの暗号化を行います。
**S3**にユーザーが保持するファイルをアップロードするケースでは、ユーザー側でファイルに暗号化やパスワード処理などを施してからアップロードを行います。
また、AWS SDKを利用することで、プログラムからS3のアップロード時にダイル暗号化も可能です。

- サーバーサイドでの暗号化（SSE：Server Side Encryption）
AWS側が自動的にファイルの暗号化処理を行います。S3やEBSをはじめ、Amazon Redshift（Redshift）、Amazon Glacier（Glacier）などのサービスで暗号化機能を提供しています。
**S3**では、バケットにデフォルト暗号化オプションを設定することで、S3バケット内に保存されるファイルが自動的に暗号化されます。
また、AWS SDKやAWS CLIを利用することで、サーバーサイドのファイル暗号化指定も可能です。
暗号化に必要な鍵には、次のいずれかを利用します。

 - ユーザーが管理している鍵
 - S3で自動生成された鍵
 - 後述するAWS KMSなどのサービスと連携して生成された鍵

**EBS**では、ボリュームの作成時に暗号化設定が可能です。
ただし、既存のEBSボリュームを暗号化ボリュームに変更するには、以下の作業を行う必要があります。

1. 既存のボリュームのスナップショットを作成
2. 作成したスナップショットを複製する際に暗号化オプションを指定
3. 暗号化されたスナップショットからEBSボリュームを再作成
4. EC2インスタンスから既存のEBSボリュームをデタッチ
5. EC2インスタンスへ暗号化されたEBSボリュームをアタッチ

##暗号化に必要な鍵の管理
データ暗号化・管理には、鍵の管理と保管が必要となります。
鍵の管理とは、鍵自体の作成、有効化や無効化、定期的なローテーションなどを指します。
主な管理方式は、鍵の管理・保管をユーザーが自身の責任で行うか、AWS側で行うかによって以下の３種類に分類されます。

【暗号化に必要な鍵の管理方式】

|鍵の管理|鍵の保管|暗号化処理|利用するAWSサービス|概要|
|---|---|---|---|---|
|ユーザー|ユーザー|CSE|ユーザー側で実施のため特になし|ユーザーが自身の責任・環境において、鍵の管理と保管を行う|
|ユーザー|AWS|CSEまたはSSE|AWS KMSまたはAWS CloudHSM（CloudHSM）|ユーザー自身が鍵の生成・管理を行うが、AWSのKMSやCloudHSMサービス上で鍵を保管する|
|AWS|AWS|SSE|各AWSサービスの暗号化機能（S3やEBSなど）|鍵の管理・保管などがすべてAWS側のサービス上で透過的に行われる|

##AWS KMSとCloudHSMによる鍵の管理・保管
AWSでユーザーの鍵の管理と保管を行うには、AWS KMSとCloudHSMのサービスを利用します。

####AWS KMSによる鍵の管理・保管

**AWS KMS**はAWS上で鍵管理するマネージドサービスで、主に暗号化鍵の作成や有効・無効の管理、ローテーション、削除などを行うことができます。
また鍵自体は、AWS上に保存されます。
たとえば、ユーザーが作成した鍵をAWS KMSで管理・保管することで、S3上のファイルのサーバーサイド暗号化（SSE）や、データ送信前にクライアントサイドでの暗号化（CSE）を簡単に行うこともできます。

AWS KMSと連携した暗号化処理が可能な主なAWSサービスには、以下のものがあります。

- AWS SDKやCLIを利用したクライアントアプリケーション
- S3、EBS、RDS、Redshiftなどのストレージやデータベースサービス

####CloudHSMによる鍵の管理・保管
もうひとつの手段として、**CloudHSM**サービスがあります。
HSM（Hardware Security Module）は、AWSのデータセンター内に配置されるユーザー占有のハードウェアアプライアンスです。
AWSがHSMのアプライアンス自体を管理し、ユーザーは自身だけがそのアプライアンスに保存される鍵を管理することができます。

HSM自体がユーザーのVPC内に配置され、ほかのネットワークから隔離されることや、国際的なセキュリティ基準（NIST FIPS140-2など）に準拠していることなどから、セキュリティコンプライアンス要件が厳しい場合に適用します。

HSMと連携した暗号化処理が可能なAWSサービスには、主に以下のものがあります。

- Redshift
- RDS for Oracle
WSLにpwsh入れてshebang(シェバン)使うとPowerShell開発で便利な時がある

基本はWSL + VSCode で開発を行っているのですが、たまにWindows向けのランチャーとか作る場合があります。

小さなツールなら簡単なPowerShellでラッパー作るだけでWindowsでも動くようになる場合もあり便利なのですが、そのためにWSL抜けるのは面倒です。

じゃあ、WSLでPowerShell開発すればいいじゃんということで、このタイトルです。


# PowerShell(pwsh)のインストール

インストールは公式の手順通りやれば簡単にできます。

https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-core-on-linux

VSCodeも当然PowerShell対応のExtentionが用意されているので、それを使います。


# shebang（シェバン）
UNIXシェルからスクリプトを実行するインタプリタを指定する `#!/bin/bash` とかの書き方です。

pwshが入っている環境で以下のように設定するだけで、実行権限つけてpwshでスクリプトが実行されるようになります。

```sh
#!/usr/bin/env pwsh
```

`/usr/bin/env pwsh` の動きはシェルから直接実行してみるとわかります。PowerShellが立ち上がります。

```sh
$ /usr/bin/env pwsh
PowerShell 7.0.2
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/powershell
Type 'help' to get help.

PS /mnt/c/Users/yusuke.otomo/> 
```

これをスクリプトファイルの先頭につけるだけです。

```powershell
#!/usr/bin/env pwsh
$MY_TEXT = "abcdefg"
Write-Output $MY_TEXT

Write-Output $PSVersionTable
```

後は `chmod +x my.ps1` みたいに実行権限つけるだけでWSL上でもPowerShellをシームレスに実行できます。（当然ですがWindows機能に依存したコマンドレットなどは実行できません）


```sh
$ ./my.ps1 
abcdefg

Name                           Value
----                           -----
PSVersion                      7.0.2
PSEdition                      Core
GitCommitId                    7.0.2
OS                             Linux 4.19.84-microsoft-standard #1 SMP Wed Nov 13 11:44:37 UTC 2019
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
```


これで、コマンドライン作るWrapperスクリプトくらいなら、WSLから出なくても開発できるようになりました。

ただし、LinuxとWindowsなので、色々と予期せぬ挙動が出る場合があります。（改行とか、変な文字コード含まれるとか）
本当に単純なスクリプト出ない限りはWindows上での開発をオススメします。
競技プログラミング練習記 No.19【ABC139練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC139](https://atcoder.jp/contests/abc139)を解きました。
4完です。

4問とも灰色difficultyですね。
E問題は難しかったです。。。
とは言いつつも、水色コーダーを目指すには解けていたい問題でした。精進します。

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A | 1min |-|5ms|
| B | 7min |-|6ms|
| C | 7min |-|23ms|
| D | 2min |mod|7ms|



## A - Tenki
```c++
	string s, t;
	cin >> s >> t;
	int ans = 0;
	for(int i = 0; i < 3; ++i)
	{
		ans += s[i] == t[i];
	}
	cout << ans;
```

## B - Power Socket
``` c++
	int a, b;
	cin >> a >> b;
	for(int i = 0; i < 30; ++i)
	{
		if ((a - 1) * i + 1 >= b)
		{
			cout << i;
			return;
		}
	}
```
1行の式にまとめられそうだったのですが、愚直にやりました。
`b`が 1 の時は答えが 0 になるので注意です。

## C - Lower
``` c++
	int n, ans = 0, score = 0;
	cin >> n;
	vector<int> h(n);
	cin >> h[0];
	for(int i = 1; i < n; ++i)
	{
		cin >> h[i];
		if (h[i - 1] >= h[i])
		{
			score++;
		}
		else
		{
			ans = max(ans, score);
			score = 0;
		}
	}
	ans = max(ans, score);
	cout << ans;
```
受け取った入力値がひとつ前の入力値よりも小さければマスを移動できます。
大きければ移動できないので、その時点で移動した距離がスコアです。
スコアのうち最大のものが答えになります。

## D - ModSum

``` c++
	ll n;
	cin >> n;
	cout << n * (n - 1) / 2;
```
シンプルですね。
`{1,2,...,N}`の数列を`{2,3,...,N-1, 1}`と左にひとつずらした場合に、求める合計値が最大となります。

...正直に書くと数学的な考察はしていません。
入力値2の`13`の答えが`78`であることと、各桁の総和を求める問題だったのでこの数式を思いつきました。


以上です。ありがとうございました。
個人的に忘れがちなpandasの書き方備忘録

### 作業用にSampleのDataFrameを作成
```python
df = pd.util.testing.makeMixedDataFrame()
df
```

|  | A | B | C | D |
|--:|--:|--:|--:|--:|
| 0 | 0.0 | 0.0 | foo1 | 2009-01-01 |
| 1 | 1.0 | 1.0 | foo2 | 2009-01-02 |
| 2 | 2.0 | 0.0 | foo3 | 2009-01-05 |
| 3 | 3.0 | 1.0 | foo4 | 2009-01-06 |
| 4 | 4.0 | 0.0 | foo5 | 2009-01-07 |



### pandasの表示オプションの変更
```python
pd.set_option('max_rows', 2)
pd.set_option('max_columns', 3)
df
```
|  | A | ... | D |
|:--|--:|--:|--:|
| 0 | 0.0 | ... | 2009-01-01 |
| ... | ... | ... | ... |
| 4 | 4.0 | ... | 2009-01-07 |


### 複数のカラムの型を変更
```python
df = df.astype({"A":"int64", "B":"int64"})
df.dtypes

```
A             int64
B             int64
C            object
D    datetime64[ns]
dtype: object

### 複数のカラムのフォーマットを変更
```python
df.assign(E=10000*df["A"])\
    .assign(F=100*df["B"])\
    .style.format(
    {
        "A":"{:.2f}", 
        "B":"{:.4f}", 
        "D":"{:%Y-%m-%d}",
        "E":"{:,}",
        "F":"{:}%"
    }
)
```
|  | A | B | C | D | E | F |
|--:|--:|--:|--:|--:|--:|--:|
| 0 | 0.00 | 0.0000 | foo1 | 2009-01-01 | 0 | 0% |
| 1 | 1.00 | 1.0000 | foo2 | 2009-01-02 | 10,000 | 100% |
| 2 | 2.00 | 0.0000 | foo3 | 2009-01-05 | 20,000 | 0% |
| 3 | 3.00 | 1.0000 | foo4 | 2009-01-06 | 30,000 | 100% |
| 4 | 4.00 | 0.0000 | foo5 | 2009-01-07 | 40,000 | 0% |


### groupbyする時のkeyをindexにしない
```python
df.groupby("B", as_index=False).agg({"A":"sum", "A":"mean"})
```
|| B | A |
|:--|:--|:--|
| 0 | 0 | 2 |
| 1 | 1 | 2 |

### Multi Indexの解除
```python
df.columns = ["_".join(index) for index in df.columns]
```
Laravelで自作Paginatorを作る

LaravelでPaginationを実装するときは、Laravelフレームワークで提供されている LengthAwarePaginatorを継承して、独自のPaginatorクラスを実装すると便利です。

ブログの記事を想定してサンプルコードを示します。

```php:PostPaginator.php
<?php

use Illuminate\Pagination\LengthAwarePaginator;

class PostPaginator extends LengthAwarePaginator {

    private $postList;

    public function __construct(PostList $list, PostCount $allCount, Limit $limit, PostStatus $postStatus)
    {
        parent::__construct($list, $allCount, limit, null, []);

        if(!is_null($postStatus) {
            $this->appends('status', postStatus);
        }
    }
}

```

このページネーターはLaravelのLengthAwarePaginatorを継承しているので、簡単に表示することができます。表示の仕方は[LaravelのPaginationリンクの表示形式を変更する](https://qiita.com/kazuhei/items/7827ecf22ef9fc3a603c)を御覧ください。

今回はブログ記事の公開、非公開というステータスを表現することを想定してpostStatusというのを追加しています。appendsの部分を追加することによって、ページネータの発行するURLのクエリパラメーターにpageだけではなく、独自のパラメーターを追加することができます。

これで手軽に独自のPaginatorを実装できます。
Active Record でよく使うメソッド

## ActiveRecordで使用するメソッド
| メソッド | 役割 | 戻り値 | 記述例 |
|:--|:--|:--|:--|
| valid? | 対象のオブジェクトが有効かどうか確認 | true or false | user.valid? |
| save | データベースに対象のオブジェクトを保存させる | true or false | user.save |
| create | モデルの生成と保存を同時におこなう | 成功：オブジェクト自身 <br> 失敗：エラー | User.create(name: 'hoge', email: 'fuga') |
| destroy | 対象のオブジェクトの削除 | 成功：オブジェクト自身 <br> 失敗：エラー | user.destroy |
| find | 引数にidを入れてデータベースからレコードを取得 | 成功：対象のオブジェクト <br> 失敗：エラー | User.find(1) |
| find_by | 引数にkeyとvalueを入れて、データベースからレコードを取得 | 成功：オブジェクト自身 <br> 失敗：nil | User.find_by(name: 'hoge') |
| update | 属性のハッシュを渡して、データベースの値を更新させる | 成功：true or 失敗：エラー | user.update(name: 'hoge', email: 'fuga') |
| update_attribute | 特定の属性のみを更新する <br> 第一引数にkey、第二引数にvalue <br> 検証の条件を無視して更新できる | 成功：true or 失敗：エラー |  user.update_attribute(:name, 'piyo') |


## 使用パターン
saveメソッドの返り値が `true` or `false` になるため、controllerのcreateアクションの実装時に使われる

```ruby:hoge_controller.rb
def create    
  tweet = Tweet.create(tweet_params)
  if tweet.save
    # 保存成功時の処理
  else
    # 保存失敗時の処理
  end
end
```
【Electorn】一括スクショ撮影ツールをElectornで作ってみました

#はじめに
一度に何十ページものスクショを撮るのって、大変ですよね。
今回はスクショ撮影作業が少しでも楽になるように一括でスクショを撮影してくれるアプリを作成しましたので、ご紹介させていただきます。

#使い方
##1.ファイルをダウンロード
https://drive.google.com/drive/folders/1r62C7TlMMo7_rN8pz1LphwNmqzSj--8F?usp=sharing
上記のURLからGithubページに遷移していただき、アプリをダウンロードしてください。
Mac OS
screen-collection-darwin-x64.zip

Windows OS
screen-collection-win32-x64.zip

##2.ダウンロードしたアプリを起動する
起動していただくと以下のようなアプリが開きます。
<img width="804" alt="スクリーンショット 2020-06-21 23.54.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251415/d9fbb8b0-d8ca-8255-2697-0c1ba94947e7.png">

##3.CSVファイルにスクショしたいページを追記する
先ほどの共有フォルダに`url.csv`があったかと思います。
そのファイルを開き、スクショしたいページのURLとタイトルを追記してください。

##4.CSVファイルとスクショの保存先を選択し、スクショ撮影
![スクリーンショット 2020-06-22 10.05.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251415/c8112f71-e077-8adc-0a61-00cfe4a8d96e.png)
・CSVファイルを選択
左のボタンをクリックすると、ファイル選択ができるようになります。
先ほど用意したCSVファイルを選択してください。

・スクショの保存先を選択
右のボタンをクリックすると、フォルダ選択ができるようになります。
スクショを格納したいフォルダを選択してください。

それぞれ、選択できたら一番下の「TAKE SCREENSHOTS!」を選択してください。
件数によって待ち時間は変動しますが、しばらく待っていると「FINISH!」と表記されます。

先ほど指定したフォルダを確認するとスクショが撮れているかと思います。

###オプションについて
オプションとして2つの機能をご用意しております。
#####1.撮影デバイス指定
デフォルトではPCになっていますが、「iPhone6/7/8」、「iPhone6/7/8 Plus」、「iPad」のいずれかに切り替えることができます。
#####2.ベーシック認証対応
ベーシック認証がかかっているページでスクショしたい場合には、「Basic Authentication」にユーザ名とパスワードを入力してください。（指定できるのは1サイトのみになります。）

###ソースコード
ソースコードは下記に公開しております。
必要に応じて、自由にカスタマイズいただいて大丈夫です！
https://github.com/lifebook-dev/screen-collection-app

アプリのビルドコマンド
（screen-collection-appディレクトリ配下でコマンド操作する）
```
Mac OS
$ npx electron-packager ./ --platform=darwin --arch=x64 --overwrite --electron-version=9.0.4

WindowsOS
$ npx electron-packager ./ --platform=win32 --arch=x64 --overwrite --electron-version=9.0.4
```

このアプリの作り方は別の記事で紹介できればと思います。
ご参考になれば幸いです！
社内勉強会でGo言語を学ぶのにやってること

# 概要
社内で勉強会の時間を取り分けることが出来たので、数人で集まって毎週2時間程度、Go言語の勉強をする事にしました。PHPプログラマや機械学習チーム、インフラさんの混成チームで、社歴も年齢も様々なので、基本的に皆Go言語の初心者としてスタートしました。(途中から詳しいメンバーが合流)

Goを選んだ理由としては、

* PHP以外の選択肢を増やしておきたい
* PHPでは難しい処理(並行処理等)が行える言語がよい
* 複数人で限られた時間で行うので、学習コストがそこまで高くない
* 業務の合間での息抜きや刺激が欲しい

と大それた志があるわけではありません。

業務ですぐいに活かせそうな、Vue.jsとも迷ったのですが、今回はサーバーサイド言語になりました。

# A Tour of Go
* https://go-tour-jp.appspot.com/welcome/1
  * 6時間程度
  * 「あーでもないこーでもない」 と言いながらドキュメントも参照しつつ動かしてみる
  * 環境作りもこの頃学ぶ

# Codewars
* https://www.codewars.com
  * 6時間程度  
  * `coding dojo` でコード戦士として `kata` を学んで `kyu` を上げていくという雰囲気のトレーニングサイト
  * 解答提出後、他の人の解答も見ることができ投票で人気のものが見れるので、初心者でイケてる書き方がわからないうちはとても参考になります


# Go言語によるWebアプリケーション開発
* https://www.amazon.co.jp/Go言語によるWebアプリケーション開発-Mat-Ryer/dp/4873117526
   * 12時間程度
   * チャットアプリケーションのサンプルアプリケーションを写経
   * 週替りで担当者を決めなんとなく司会進行、時間配分等を主導
   
# 社内ツール作り
* https://github.com/google/go-github を使ったアプリ
  * 8時間(4週間)〜現在
  * モブプログラミング形式(ドライバーとモブたち)
  * 内定の出ているメンバーも参加するようになり、 ミニプロジェクトとしてプロダクトオーナーを立て要件決め、設計と普段の開発フロー風に実施
  * 業務遂行より、お勉強がメインなので「とにかく作ってみよう要素」が強い為、アジャイルに最低限の機能から実装して動かしていくスタイルを採用


# おわりに
1週間に1回だと毎回思い出すのに苦労することや、メンバーによって普段の学習の方法や観点が違っていること、いわゆる先生がいない時期は全員分からない状況になったこと等、今までもこれからも考慮・改善すべき点はありますが、普段は1人でやる学習をこうして色々な人と出来るのは貴重ですし思った以上に面白いですね✨

初心者が集まって言語を学んだサンプルとして参考になれば幸いです。
もう少し続けて良かったことなど本記事を更新出来ればと思います。
RailsのTips

*個人的な備忘録となります*
## 目次
- [データベースのインスタンスにアクセスするとき、.(ドット)+カラム名で値が取得できる理由](#データベースのインスタンスにアクセスするとき、.(ドット)+カラム名で値が取得できる理由)

#### データベースのインスタンスにアクセスするとき、.(ドット)+カラム名で値が取得できる理由
Active Record を継承したクラスで作られたインスタンス（オブジェクト）だから、.メソッドを使って値の取得が可能になっているから。
通常のRubyの記法ではないため、ハッシュオブジェクトに対して値を取得したいからドットで書いたらエラーになる。

###### Rubyにおけるハッシュの値の取得方法
```ruby:example.rb
hash = {name: 'hoge', email: 'fuga@example.com'}

hash[:name]
=> "hoge"

# .で取得しようとするとエラーになる
hash.name
NoMethodError (undefined method `name' for {:name=>"hoge", :email=>"fuga@example.com"}:Hash)
```

###### ARを継承するクラスから作られたオブジェクトにおける値の取得方法
```ruby:example.rb
# すでにHashクラスが定義されている前提で、Hash.newでインスタンスを作成
hash = Hash.new(name: 'hoge', email: 'fuga@example.com')

hash[:name]
=> "hoge"

hash.name
=> "hoge"
```
Markdown の laziness とは

[CommonMark の重要な概念、段落の interrupt とは](https://qiita.com/tk0miya/items/89c39281a430081f1747) という記事の最後にこんなことを書いていたことに昨晩気づきました。

>そのうち暇を見て、逆のパターンである「他の要素の直後に、段落を書いた場合の挙動」について説明しようと思います。

すっかり忘れてしまっていたのですが、予告(?)をすっぽかすのもアレなので、まとめてみたいと思います。

## 前回のおさらい

* CommonMark には**段落の interrupt**という概念がある
* いくつかの記法は段落に割り込むことができ、空行無しで別の要素を開始できる
* たとえば、以下の例は段落に箇条書きが割り込む例

  ```markdown
  段落1です。
  * 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
  ```

## 他の要素の直後に段落を書く

では、このサンプルの行を入れ替えてみましょう。

```markdown
* 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
段落1です。
```

これはどう解釈されるでしょうか。Qiita でのレンダリング結果を見てみましょう。

* 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
段落1です。

「段落1です。」の部分は新しい段落ではなく、箇条書きの一部としてみなされていますね。これが Markdown の特徴のひとつでもある、lazy continuation です[^1]。Markdown ではリストや引用ブロックを書く際、2行目以降はインデントや引用符を省略しても良いというルールがあります。先ほどの箇条書きの例は

```markdown
* 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
  段落1です。
```

と等価であると認識されているわけです。インデントせずに済むって便利ですね。まさに怠惰だ！
なお、lazy continuation は空行かほかのブロック要素が登場するまで続きます。

[^1]: Markdown では単に lazy、CommonMark では lazy continuation (line) と呼ばれています

この動作は、他のドキュメントからテキストを切り貼りするときに非常に便利です。段落をまるっとコピペして、先頭にリストマーカーや引用符を書くだけでまるごと箇条書きや引用ブロックに仕立てることができます(ただし、空行が登場すると lazy continuation の効果がなくなるのでご注意を)。

## lazy continuation ができる記法とできない記法

lazy continuation ができるのは箇条書き(番号なし、番号付き)と引用ブロックのみです。他の記法では対応していません。

```markdown
* 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
段落1です。
```

```markdown
1. 空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
段落1です。
```

```markdown
>空行をはさまずに箇条書きを書いても、ここはリストとして認識されます。
段落1です。
```

CommonMark でいうところの Container Block (他の要素を内包できるブロック要素)で使えるということですね。

## まとめ

* Markdown には lazy continuous という概念がある
* 箇条書きと引用ブロックを書く際に、継続行のインデントやマーカーを省略できる仕組み
* 新しい段落のつもりが箇条書きの一部になることがあるのでご注意ください
JavaScript: [🐈, 🐕, 🐕, 🐈, 🐈, 🐕]のような配列を[[🐈, 🐈, 🐈 ], [🐕, 🐕, 🐕]]に仕分けする

JavaScriptの配列を要素の内容に応じて、2つのグループに仕分け(partitioning)する方法です。

下の例では、要素が犬か猫かによって仕分けしています:

```javascript:partition.js
const pets = ['🐈', '🐕', '🐕', '🐈', '🐈', '🐕']

const [cats, dogs] = pets.reduce(
  ([cats, dogs], pet) =>
    pet === '🐈' ? [[...cats, pet], dogs] : [cats, [...dogs, pet]],
  [[], []]
)

console.log(cats, dogs)
//=> [ '🐈', '🐈', '🐈' ] [ '🐕', '🐕', '🐕' ]
```

ちなみにTypeScriptでは`reduce`の型引数に`[string[], string[]]`を指定します:

```typescript:partition.ts
const pets = ['🐈', '🐕', '🐕', '🐈', '🐈', '🐕']

const [cats, dogs] = pets.reduce<[string[], string[]]>(
  ([cats, dogs], pet) =>
    pet === '🐈' ? [[...cats, pet], dogs] : [cats, [...dogs, pet]],
  [[], []]
)

console.log(cats, dogs)
```

仕訳処理を汎用化すると:

```partition.js
const partition = (array, predicate) =>
  array.reduce(
    ([left, right], value) =>
      predicate(value) ? [[...left, value], right] : [left, [...right, value]],
    [[], []]
  )
const pets = ['🐈', '🐕', '🐕', '🐈', '🐈', '🐕']
const [cats, dogs] = partition(pets, value => value === '🐈')
```

```partition.ts
const partition = <
  T extends ReadonlyArray<any>,
  U extends T[number],
  V extends Exclude<T[number], U>
>(
  array: T,
  predicate: (value: T[number]) => value is U
): [U[], V[]] =>
  array.reduce(
    ([left, right], value) =>
      predicate(value) ? [[...left, value], right] : [left, [...right, value]],
    [[], []]
  )

const pets = ['🐈', '🐕', '🐕', '🐈', '🐈', '🐕'] as const
const [cats, dogs]: ['🐈'[], '🐕'[]] = partition(pets, (value): value is '🐈' => value === '🐈')
```

---

最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローしてもらえると嬉しいです:relieved:→[Twitter@suin](https://twitter.com/suin)
[TypeScript]Tupleに対してincludes()を使用しようとしたらハマった

あるリストからTupleで持ってるものをチェックしようとしたらエラーが出てハマりました。
雰囲気はこんな感じです。

```typescript
const checkList = ["a", "b", "c"] as const;
hogeList.every(
  (hoge: string) => checkList.includes(hoge) // エラー！！
);
```
エラー内容：
`型 '"hoge"' の引数を型 '"a" | "b" | "c"' のパラメーターに割り当てることはできません。`

`includes()`の期待する引数は、`"a" | "b" | "c"` のみということなんですが、includesの使い方（？）を誤認していて何が起きているのか最初理解できませんでした。。


## 回避策

### その1

```typescript
const checkList = ["a", "b", "c"] as const;
(checkList as ReadonlyArray<string>).includes("hoge");
```

### その2

```typescript
const checkList: string[] = ["a", "b", "c"];
checkList.includes("hoge");
```
UBUNTU＋PX-Q3U4でSUSPENDが効かない件

UBUNTUでSUSPENDが効かず、
KERNELを変更したりしても治らずずーっと謎であった。

EPG取得のためRECPT1が可動中は、正常にSUSPEND出来ない事に気がついた。
SUSPEND前に、RECPT1を停止できればいいが。

/etc/systemd/system/
へMIRAKURUNを停止するSCRIPTを書くが何故か機能しない。

うまく行くようになったら再投稿予定。
[Rust] AtCoderをやる Rustを褒める C++と比べる

# 目標

Rustの良いところを他の言語 (とくに C++) と比較して考察しながら、AtCoderに慣れていく


# C++ の問題点

RustもC++と同様にスマートポインタやコンテナがあるが、所有権や借用の概念により、それはつまり、自分でメモリの確保と解放を行わなくて良いということになる

他言語にはガベージコレクタという機能を持つものが存在し、メモリを自動で管理してくれて便利なこともある

ガベージコレクタはとても賢いが、万能ではない
なぜなら、 ~~ほとんどのデータをヒープに (メモリ領域が明確になるスタックと違い、ただ漠然とメモリ領域を確保する) に置き参照経由で扱わなければならず、~~ 実行速度にも多少影響する

また、C++のスマートポインタは不正な状態のポインタの使用を完全に防ぐことはできない

特にイテレーションはコレクションに対する走査を行うための標準的なツールにもかかわらず実質的に単なるポインタと同様なので、しばしば無効なイテレータが発生する

C++ より Rust を学ぶことを推奨


## イテレータの無効化

イテレート中に要素の追加などのイテレータを無効化する操作を行うと実行時エラーが発生する

配列外参照により segmentation fault となることもある (ローンチ後にこのエラーになると面倒)
これらが無駄なデバッグ時間をつくる

Rust ではイテレータを無効化する操作はコンパイルエラーになるため、誤ったコードを書いてもすぐ気づける


## 暗黙の型変換

longコンテナの全要素の総和をしようと、accumulate関数で総和を計算しようとすると、関数が暗黙の型変換をしてintで総和を計算しようとしてオーバーフローになる

```cpp
#include <iostream>
#include <limits>
#include <numeric>
#include <vector>

int main() {
    // long long で表せる最大値を`large`とする。
    long long large = std::numeric_limits<long long>::max();

    std::vector<long long> s = {large};

    // sには`large`しか入っていないので、総和は普通に`large`になるはず。ところが
    // 総和の型をint型だと思って計算してしまいオーバーフローを起こしてしまう。
    // コンパイルエラーも実行時エラーも起こらない！
    std::cout << std::accumulate(s.begin(), s.end(), 0) << std::endl;

    // 正しくは以下の通り。
    std::cout << std::accumulate(s.begin(), s.end(), 0LL) << std::endl;
}
```

Rust は整数の暗黙の型変換を認めていないので、型の一致でコンパイルエラーになる

```rust
let s = vec![std::i64::MAX];
let x: i32 = s.into_iter().sum();
// E0277: the trait bound `i32: std::iter::Sum<i64>` is not satisfied
// 3 | let x: i32 = s.into_iter().sum();
//   |                            ^^^ the trait `std::iter::Sum<i64>` is not implemented for `i32`
```


## Rust コンパイラのエラーメッセージは親切

C++ のテンプレートでは、テンプレート引数が不正なとき、実体化のタイミングでエラーが発生する
そのためエラーメッセージが大量に発生することがある
ぎっちぎちで読みにくいし、ヒントも親切とはいえない

Rust には、コンパイル駆動設計という言葉があるぐらいにコンパイルエラーが読みやすい

エラーが関連する他の場所や修正方法のヒントなどをわかりやすく表示してくれる

トレイトやジェネリクスの仕組みによりエラーの所在が明確化されているので、コンパイル時にエラーの存在を教えてくれる


# リンク集

[AtCoderで使用できるクレート最新情報](https://github.com/rust-lang-ja/atcoder-rust-resources/wiki/2020-Update)
[プログラミング言語Rust入門](https://amzn.to/2BkGP0n)
[実践Rust入門](https://amzn.to/2zRbu4W)
[C++入門](https://amzn.to/2Nf1ntW)
Docker初学者によるまとめ#1

# Docker初学まとめ

## 仮想マシンとコンテナ型仮想化の違い
### 仮想マシン
- 一つの仮想マシンはゲストOS、ライブラリ/ミドルウェア、アプリケーションで構成
- ホストOSとは違うOSを建てることも可能
- 割り当てられるリソースが大きい（CPU/メモリ）

### コンテナ型仮想化
- 一つのコンテナはライブラリ/ミドルウェア、アプリケーションで構成
- 実行はホストOSで行われるため別OSをベースとしたコンテナを実行することはできない
    →DockerforMacといったソフトウェアではLinuxの仮想マシンを立ち上げその上でLinuxのコンテナを起動させている
- ゲストOS実行がない分割り当てられるリソースが小さい

## Docker run コマンドについて
### 行なっていること
1. イメージがLInuxの仮想マシン上にあるか確認
2. なければDockerHubを用いてインストール
3. イメージを基にコンテナを作成、起動

### runコマンドは複数のコマンドの一括実行コマンド
- docker pull: イメージのダウンロード
- docker create: イメージからコンテナの作成
- docker start: コンテナの起動
eclipse Javaソースコード入力する際、自動補完トリガーの有効化設定（auto activation triggers）

##eclipseの自動トリガー補完
eclipseを使用するメリットの一つは、Javaソースコード入力する際に、自動補完トリガー機能です。しかし、普段の操作で、「.」を入力した後に効きますが、それより、もっと活用させたい時の設定方法がありますでしょうか。
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609143/46a2270f-cb97-09c9-28a1-da8d23d28bc1.png)
##設定手順
eclipse > ウインドウ(W) > 設定(P)
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609143/fe02b426-1bfc-22b0-a4da-4831e74ae068.png)

Java > エディター > コンテンツ・アシスト > 自動有効化　から設定する
![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609143/23ad533f-f913-37d0-2c42-5202a6b42441.png)

- 自動有効化遅延(ミリ秒)：0

```bash:デフォルト値：0　⇒　下記に変更
80
```
- Javaの自動有効化トリガー：.

```bash:デフォルト値：　⇒　下記に変更
.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_
```
- Javadocの自動有効化トリガー：@#

```bash:デフォルト値：@#　⇒　そのままで良い
@#
```

「適用して閉じる」を押下したら、Javaソースコードを入力してみましょう。
![04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609143/e25fe640-7d64-9671-cec4-ed80dfec4e45.png)
##参照
https://www.christianschenk.org/blog/eclipse-java-content-assist-auto-activation-triggers/
API Gateway + Lambda のCORS関連エラーの対策

API Gateway と Lambda でウェブアプリのAPIエンドポイントをつくって外部サイトのシステムから呼び出そうとしたらCORS（Cross-origin resource sharing）のエラーになってしまい、設定に躓いたのでメモ

# 基本的な対策
## API Gateway でCORS有効化
API Gateway のアクションからCORSの有効化を設定するのが基本的な対策です。
通常はこれでOKのはず。

## エラーが出て設定が反映できないとき
自分の環境で、以下のようなエラーがでてうまく設定ができませんでした。
`Invalid Response status code specified`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73833/6daf7c6f-67d3-292a-010e-60d04c2f7333.png)

### 対策（レスポンスヘッダーを手動で設定）

1. 上記画面でエラーになった内容をメモ
2. リソースからエラーになっているメソッド（GETとかPOSTとか）を選択
3. レスポンスの追加を選択
4. HTTPのステータスに200を入力して確定（チェックマークみたいなのをクリック）
5. 200の左あたりに▶が表示されるのでそれをクリックして開く
6. 200のレスポンスヘッダーの入力欄が表示されるのでエラーになっていたヘッダーを設定

### 画面
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73833/6607e507-68af-b942-1047-936941f4a7cd.png" width="280px">
↑ここを選択して
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73833/e4103c72-c9e0-2e31-2817-d0ac998c1e66.png" width="280px">
↑こんな風に手動設定

### 確認する
上記を修正して、もういちどCORSの有効化をおこなうと、ヘッダーを記入したメソッドはエラーが解消されている。
全てのメソッドに対して上記方法で手動設定したところCORS有効化時のエラーがでなくなりました。
（Access-Control-Allow-Origin 統合レスポンスヘッダーマッピング）というのだけ、エラーが解消できないことがありましたが、とりあえずアクセスはできました。たぶん下のLambdaほうで解決できているのかな？と思っています。

**（！）CORSの有効化をおこなったらデプロイを忘れずに！**
統合なんちゃら以外エラーが解消したいのに相変わらずアクセスできない等のときは、API Gatewayのデプロイを忘れずに。（慣れている人は当たり前なのかもだけど自分はデプロイ忘れていて途方にくれました）

## Lambdaのレスポンス

上記でAPI GatewayのCORSは設定できるけれど、その先がLambdaの場合は、Lambdaのレスポンスも設定しないといけないです。とりあえず全部許可する場合は、こんな感じになります。

```javascript
exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET"
        },
        'body': JSON.stringify({
            message: 'hello world Test2!!',
        })
    };
    return response;
};
```




# 参考
https://stackoverflow.com/questions/45820769/fail-to-enable-cors-for-api-gateway-functions
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-cors.html
モバイルデバイスのときにだけボタンを表示させたい


#はじめに

Webアプリケーションを作っていると、モバイルデバイスのときだけNavigationBarのボタンを表示させたいということがよくあるので方法を紹介する。

なお前提としてUIフレームワークはVuetifyを使っているものとする。

# 制御にはBreakpointを使う

[公式](https://vuetifyjs.com/ja/customization/breakpoints)で紹介しているBreakpointを使うのが良い。

```$vuetify.breakpoint``` という変数には現在の画面サイズに関する状態が保持されている。

![スクリーンショット 2020-06-22 9.29.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200963/137b9e40-cf10-254f-e146-d7926b1cc24d.png "スクリーンショット 2020-06-22 9.29.41.png")


たくさんパラメーターがあるのでどれを使っても良いが、例えば ```xs``` を利用して制御を行うとこんな条件になる。

```
v-show="$vuetify.breakpoint.xs"
```


実際のソース上のではこんな感じ

```
<template>
  <v-app dark>
    <v-navigation-drawer
      v-model="drawer"
      :mini-variant="miniVariant"
      :clipped="clipped"
      fixed
      app
    >
      <v-list>
        <v-list-item
          v-for="(item, i) in items"
          :key="i"
          :to="item.to"
          router
          exact
        >
          <v-list-item-action>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-action>
          <v-list-item-content>
            <v-list-item-title v-text="item.title" />
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
    <v-app-bar :clipped-left="clipped" fixed app>
      <v-app-bar-nav-icon
        @click.stop="drawer = !drawer"
        v-show="$vuetify.breakpoint.xs"      <-------ここに一行追加
      />
      <v-spacer />
    </v-app-bar>
    <v-main>
      <v-container fluid>
        <nuxt />
      </v-container>
    </v-main>
    <v-footer :absolute="!fixed" app>
      <span>&copy; {{ new Date().getFullYear() }}</span>
    </v-footer>
  </v-app>
</template>
```

これで晴れてモバイルデバイスで表示している時のみメニューバーボタンが表示されるようになる。
アソシエーションの概念について

# アソシエーションとは
例えば、ブログを投稿したユーザー名を表示するには、ユーザーとブログモデルを関連付ける必要があります。
このような2つの**モデル間の関連付け**のことをアソシエーションといいます。
そして、この関連付けには外部キーが必要になってきます。

## 外部キー
外部キーとは、複数のテーブルを結びつける時に使用するカラムのことです。
関連付けのために、テーブルに関連付け用のカラムを追加します。
外部キーは関連付け先のテーブルでは主キーになります。

（例）ユーザー全員がuser_idという名札をつけることにより、ブログとの結びつきを表す、というのが外部キーのイメージです。
この時、一人のユーザーが複数のブログを所有するという関係性が成り立つので、ブログとユーザーは、一対多の関係性で紐づいていると言えます。
Blogテーブルにuser_idがあったら、user_idはusersにおいては主キー、blogテーブルでは外部キーと呼ばれます。


また、`どちらが主で、どちらが従なのか？`という視点は、アソシエーションを設計する際にとても重要な情報になります。




### 外部キーの設定方法
実際にアプリを作り、動きを見ていきます。
既にUserモデルが作成されていると想定します。さらにBlogモデルも作成しますが、BlogモデルとUserモデルの関連付けをするために、テーブルに関連付け用のカラム（外部キー）を追加することが必要です。
それでは、blogテーブルにuser_idカラムを追加していきます。

```console
rails g model Blog title:string content:text user:references
```

のように、 `user:references`をつけて実行することで、Userモデルと関連付けするための外部キーを備えた、以下のようなマイグレーションファイルが出来上がります。

```ruby:db/migrate/xxxxx_create_blogs.rb
class CreateBlogs < ActiveRecord::Migration[5.2]
  def change
    create_table :blogs do |t|
      t.string :title
      t.text :content
      t.references :user, foreign_key: true
      t.timestamps
    end
  end
end
```

このように、

```
t.references :user, foreign_key: true
```

というコードが自動的に含まれています。foreign_key = 外部キー指定です。

### 外部キー制約とは

主キーと外部キーを使った制約のこと。
外部キー制約により、

- 存在しない値の外部キーが登録できない
- 親テーブルに外部キーが登録されている子テーブルのリソースが削除できない

というメリットがあります。
【メモ】GeoTiff から テキストデータに変換する

# 背景

いくつかの解像度で所有しているGeoTiffデータを一度にテキストデータに変換したかったので調べたところ、下記のQAサイトに答えが載っていた（いつも通り、消える前にメモする）。

【出典】[Geotiff画像からCSVファイルへの出力 | QGIS初心者質問グループ(Googleグループ)](https://groups.google.com/forum/#!topic/qgisshitumon01/SCWhU8Jm_qE)

# 解法

実行環境

```
Ubuntu 18.04.1
GDAL 2.2.3, released 2017/11/20
```

スクリプト

```geotiff2xyz.sh
#! /bin/bash
for i in 10 20 30; do
  # 緯度経度に変換
  gdalwarp -of GTiff -t_srs EPSG:4326 data${i}m_UTM.tiff data${i}m_EPSG4326.tiff
  # GeoTiff -> Text
  gdal_translate -of XYZ -co COLUMN_SEPARATOR=, data${i}m_EPSG4326.tiff data${i}m_EPSG4326.xyz
  # 用いたデータでは Nodata の領域で 3.4028234663852886e+38 が出力されるが、 除外方法が分からないので、下記で除去
  cat data${i}m_EPSG4326.xyz | grep -v 3.4028234663852886e+38 > data${i}m_EPSG4326_nd.xyz
done
```

# 補足

変換したいデータがUTM座標系であったので、元記事通り緯度経度に変換した後にテキストへ変換した。<del>元記事ではCSVへの変換として `COLUMN_SEPARATOR=,`が用いられているが、自分の使用環境では`Warning 6: driver XYZ does not support creation option COLMUN_SEPARATOR`という警告が出てスペース区切りのXYZが生成された</del>（エラーはスペルミス）。Nodataや特定の数値の除外方法は良く分からない。
go修行9日目　ポインタとか


## ポインタ型

 - `&n`でポインタのアドレスを指定
 - `*int`で指定したアドレスの中身を取得

```golang

package main

import "fmt"

func main() {
	var n int = 100
	fmt.Println(n)
	fmt.Println(&n)

	// pはポインタ型
	var p *int = &n

	fmt.Println(p)

	fmt.Println(*p)
}
```

```
100
0xc000104030
0xc000104030
100
```


## newとmake

```golang

package main

import "fmt"

func main(){
	// メモリのアドレスを確保している
	var p *int = new(int)
	fmt.Println(p)

	// メモリのアドレスは確保していないのでnil
	var p2 *int
	fmt.Println(p2)
}
```

```
0xc0000120b8
<nil>
```

## struct

```golang

package main

import "fmt"

type Vertex struct{
	X,	Y int
	S string
}

func main() {
	// XとYを指定して数値を入れる
	v := Vertex{X: 1, Y:2}
	fmt.Println(v)
	fmt.Println(v.X, v.Y)
	v.X = 100
	fmt.Println(v.X, v.Y)

	// Xだけ入れるとＹは0扱い
	v2 := Vertex{X: 1}
	fmt.Println(v2)

	// XやＹを指定しない場合  文字列も含む
	v3 := Vertex{1,2,"test"}
	fmt.Println(v3)

	// なにも入れない場合はデフォルトの0か空文字が入る
	v4 := Vertex{}
	fmt.Println(v4)
}
```


```
{1 2 }
1 2
100 2
{1 0 }
{1 2 test}
{0 0 }
```

## コンストラクタ

？？？

```golang

package main

import "fmt"

type Vertex struct{
	//小文字にするとx.yを書き換えられる
	x, y int
}

func (v Vertex) Area() int{
	return v.x * v.y
}

func (v *Vertex) Scale(i int){
	v.x = v.x * i
	v.y = v.y * i
}

func New(x, y int) *Vertex{
	return &Vertex{x, y}
}

func main(){
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Area())
}
```

```
1200
```
プログラミング初心者のためのコンパイラ作成入門？

teratailに、flexを動かすコードの一部を改変したいという質問があったので回答しようと思っていましたが、質問を取り下げたみたいなのでQiita記事にアップしておきます。

# 回答

flexというのはレキシカルパーサ（字句解析）ツールのことであって、あなたはコンパイラか何かを作りたいということでよろしいでしょうか。もしそうであれば、あなたはC言語の初歩的な扱い方を理解していないのでflexとyacc(またはbison)を正しく扱えないと考えます。

### コンパイラを作るには

コンパイラはこのような工程を経ます(すいません、手元に文献がないのでwikipediaを参考にしています)。

1. 字句解析
2. 構文解析
3. 中間コード生成(省略可能)
4. 最適化
5. コード生成

コンパイラのフロントエンドと呼ばれる部分は字句解析と構文解析ですが、そのためにflexとyaccを援用します。コンパイラを作成する方法としては、フルスクラッチで記述する方法が最近の流行だったと思います。flex, yaccと同じくらいポピュラーな方法としてはLVMMを使用することです。

[低レイヤを知りたい人のためのCコンパイラ作成入門](https://www.sigbus.info/compilerbook)

### コンパイラのフロントエンドを理解する３ステップ

コンパイラのフロントエンドはテキストを解釈するのでパーサーと呼ばれますが、これを理解するためにはこの手順を踏まなければなりません。

1. printf, scanfのフォーマットを理解する
2. 正規表現を理解する
3. パーサージェネレータ(yacc, bison, LVMM等)用の記述方法を理解する

各ステップの間には目に見えない壁があります。一朝一夕でできるようなものではなく、たいていのプログラマはパーサージェネレータを使うことを断念します。

### 問題の箇所は？

今回の問題の箇所は、printf, scanf, fopenと続く３文です。ここは普通のCプログラマなら分かって当然の箇所であり、例えば`abc.txt`を入力にしたければ`yyin = fopen("abc.txt", "r");`と書けばいいということは誰にも分かることです。つまり、質問者さんは先ほどの「コンパイラのフロントエンドを理解する３ステップ」の1ステップ目も達成できていないわけです。

そのようなわけで、プログラミングというのは本を読んでやればできるというような甘いものではありません。プログラミングに関する膨大なトピックのうち、分かりやすいものを自分で見つけてきて少しずつ吸収するといったことが必要になります。

printf, scanfを含んだC言語の初歩を学ぶ一番の方法はAOJ(Aizu Online Judge)の初歩的な問題を解くことです。C言語の信頼できるソースとしてはC言語の仕様書がありますが、これは有料です。UNIXのmanページ(これはインターネットで「printf man」などと検索すれば出てきます）は割と正確です。仕様書のドラフト（草稿、未定稿、途中の稿のこと）がネット上にアップされているのでそれを活用している人もいます。基本的にはインターネットで検索して情報収集することになりますが、できるだけ信頼性の高いサイトを見ることをおすすめします。
【Node.js v11】ディレクトリ内のファイルパスを再帰的に取得するワンライナー

ディレクトリ内全てのファイル一覧を取得するというありふれた処理ですがたまたまワンライナーを思いついたのでメモ代わりに紹介します
同期メソッドなので使いどころには注意してください

## JavaScript

```javascript
const fs = require('fs')

const listFiles = (dir) =>
  fs.readdirSync(dir, { withFileTypes: true }).flatMap(dirent =>
    dirent.isFile() ? [`${dir}/${dirent.name}`] : listFiles(`${dir}/${dirent.name}`)
  )

console.log(listFiles('hoge/fuga'))
```

fs.readdirに `withFileTypes: true` オプションが追加されてたんですね、最近知りました
https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options

`${dir}/${dirent.name}` を2回書くのは良くないので実際に使う場合はワンライナーにこだわらず変数に入れるのがいいです
flatMapを使ってるのでNode.js v11以上じゃないと動きません

## TypeScript

```typescript
import fs from 'fs'

const listFiles = (dir: string): string[] =>
  fs.readdirSync(dir, { withFileTypes: true }).flatMap(dirent =>
    dirent.isFile() ? [`${dir}/${dirent.name}`] : listFiles(`${dir}/${dirent.name}`)
  )

console.log(listFiles('hoge/fuga'))
```

requireをimportに変えて、引数と返り値に型を指定しただけです

普段はTypeScriptのフレームワークをOSSで開発してるのでTwitterも見ていってください
[Twitter@m_mitsuhide](https://twitter.com/m_mitsuhide)
GIACのCPEを稼ぐ方法

**2024/4/16　最新のCPEルールに合わせて更新しました。**

# はじめに
CISSPなどの多くのセキュリティ資格が継続して教育を受けることで更新できるように、GIACの資格もまた更新時までにCPEを貯める必要があります。
GIACの場合は4年間で36CPEです。CISSPが3年で120CPEなので楽勝かと思いきや、意外と大変そうという内容になります。

# GIACの資格
GIACはサイバーセキュリティ資格を多く提供しています。私の周りで取得している人ですと、GPEN、GWAPT、GCFA、GCFE、GREMあたりが多い印象です。

# GIACの更新方法
GIAC資格の更新はCPEを4年間で36ポイント貯めるか、最新バージョンの試験に合格することが条件です。これ以外に、GSPまたはGSEを取得することでも更新できますが、条件を満たすことが難しいためここでは触れません。
更新は資格の有効期限の2年前から行えます。

## 試験に合格して更新する
最新版の試験を受けることを選択した場合、最新版のコース教材がSANSのアカウントに付与された上で印刷されたテキストが郵送されます。一度合格している試験ですので、保持しているGIAC資格が少ないのであればこの方法が楽かもしれません。4年に1回だけですし、万一落ちても有効期限までは資格を失うわけではないので何度かチャレンジすれば合格することは可能でしょう。

## CPEで更新する
GIACのルールによると、CPEは4年間で36ポイント貯めればよく、3年間で120ポイント貯める必要があるCISSPと比べるとかなり少ないように見えます。
CPEのカテゴリは以下に記載されています。

https://www.giac.org/renewal/cpe-information/

各カテゴリについての詳細は以下に説明があります。

https://www.giac.org/knowledge-base/renewal/

# CPEカテゴリ
ここからはCPEの各カテゴリについて解説していきます。

## SANSのトレーニングや新しい資格を取得
SANS Training, New GIAC Certificationは、SANSのトレーニングを受けるか、トレーニングなしで新しいGIAC資格を取得するという方法になります。会社が出してくれるのであれば、トレーニングを受けるのが最も簡単です。
この方法で獲得できるCPEは最大36、最大で5つの資格に対して適用可能なため、多数のGIACを保有している場合は最も効率的です。

なお、トレーニングなしで新しいGIAC資格を取得するのは難しいと感じるかもしれませんが、GIACであればどれでも良いようなので、GSECやGCIHなど比較的簡単な試験を受けてみるのはアリだと思います。実際私はこれらの試験をトレーニングなしで合格しています。

## ISO-17024の認定を受けたトレーニングを受講
[このリスト](https://www.ansi.org/accreditation/credentialing/personnel-certification/ALLdirectoryListing?menuID=2&prgID=201&statusID=4)にあるトレーニングまたは資格のうち、自身が取得している資格に関連するトレーニングを受講または資格を取得することで、CPEが獲得できます。

日本で比較的有名な資格ですと、[ISC2](https://www.ansi.org/accreditation/credentialing/personnel-certification/AllDirectoryDetails?&prgID=201&OrgId=97&statusID=4)（CISSPやSSCPなど）、[CompTIA](https://www.ansi.org/accreditation/credentialing/personnel-certification/AllDirectoryDetails?&prgID=201&OrgId=93&statusID=4)（CompTIA Security+など）、[ISACA](https://www.ansi.org/accreditation/credentialing/personnel-certification/AllDirectoryDetails?&prgID=201&OrgId=96&statusID=4)(CISA、CISMなど）です。

新規に取得する必要はあるものの、日本でも保有者が多い有名な資格がたくさんリストにありますので、未取得の資格が1つはあると思います。
比較的難易度の低いものもありますので、比較的簡単に36CPEすべてを申請できると思われます。

このカテゴリのCPEは2つのGIAC資格に適用可能です。

## 大学院のコース、本の出版
大学院レベルのコースを修了する、あるいは資格に関連した本を出版する方法です。
大学院はなかなか社会人には厳しいかもしれません。本の出版ですが、18ページ以上のテキストがあれば36CPE獲得できます。同人誌でも良いかと思いましたが、出版社を記載する必要があるようで、通常はなかなか厳しいかもしれません。

## その他の方法
その他とまとめてしまいましたが、以下の4つのカテゴリの方法が最も現実的と思われます。

| 項目 | 最大CPE数 |
|:-----------:|:-------:|
| セキュリティ関連トレーニング  | 18  |
| サイバーレンジ/演習  | 12  |
| 業務経験  | 12  |
| コミュニティ活動  | 12  |

セキュリティ関連トレーニングは、例としてAWS、Black Hatなどが挙げられています。これに限定されないとのことですので、各セキュリティベンターが提供するトレーニングでも問題ないと思います。国内ですと、CODE BLUEやJSACといったイベントでも該当すると思われます。
一般的なトレーニングであれば2～3日間行われますので、12～18CPEが獲得できます（1日のトレーニングで6CPEです）

サイバーレンジ/演習は、[NetWars](https://www.sans.org/netwars/)が該当します。ただし、それなりの金額（20万円ほど）を支払う必要があるようです。4年に1回参加と考えればなんとか個人でも支払える金額かもしれません。

業務経験は、通常の業務だけで稼げるようです。1年間の業務経験で12CPEです。

コミュニティ活動は、ウェブキャスト/ポッドキャスト/ウェビナーの参加やブログの執筆でも良いようです。比較的稼ぎやすい活動になると思います。これも12CPEに限定されています。

NetWarsは2つ、それ以外は1つのGIAC資格にしか適用できないため、多数のGIAC資格を保有している場合は厳しいです。

#まとめ
会社が出してくれるのであれば、SANSのトレーニングを受けるのが最も簡単、そうではないという人は、業務経験、ブログの執筆、関連するトレーニングの受講などで細々と稼ぐのが良さそうです。頑張りましょう。
なお、SANS Japanのページにも同じような記載があります。
https://www.sans-japan.jp/giac_renewal
LaravelのミドルウェアでDBにアクセスログを残す

Laravelアプリの検索フォームのリニューアル時に、ユーザーへのアンケートではなく、chromeの開発チームのように利用統計から改善したいと思いました。

最も利用される検索フォームは電話番号か氏名のどちらか、と調べられたり、レスポンス改善の優先度を見える化するためにミリ秒単位でロード時間を測るまでをゴールとします。

ミドルウェアを使って、簡単に実装できました。ファイルもartisanコマンドで作成できます。

```
$ php artisan make:model HttpRequest --migration
Model created successfully.
Created Migration: 2020_06_20_010616_create_http_requests_table

$ php artisan make:middleware CollectHttpRequestStat
Middleware created successfully.
```

作成された３ファイルに[https://github.com/umihico/laravel-demo/commit/4a5e2a3](https://github.com/umihico/laravel-demo/commit/4a5e2a3)のように修正し、マイグレーションを実行します。

```
$ php artisan migrate --path=database/migrations/2020_06_20_010616_create_http_requests_table.php 
Migrating: 2020_06_20_010616_create_http_requests_table
Migrated:  2020_06_20_010616_create_http_requests_table (0.05 seconds)
```

デプロイすると、この画像のような形でDBにデータが取れるようになります。
複数アプリがあることを想定し、APP_NAMEを挿入しています。ログインしていればユーザーIDが入ります。検索クエリーはdataカラムに、レスポンス時間はmillisecondsカラムに入ります。

<img width="802" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256466/697b373c-364a-0b25-56c5-5b20d952862d.png">

以上です。