OmniAICreator/Qiita-1.07M huggingface dataset:
MahApps.Metro.IconPacksで簡単にアイコンを使う方法

# 必要な準備・手順
VisualStudio2022でWPFプロジェクトの場合の手順です。

1. MahApps.Metro.IconPacksインストール（Nuget Package）
1. IconPacks-Browserのインストール
1. 使い方


# 1. Nuget Packageインストール
「MahApps.Metro.IconPacks」で検索し、インストールしてください。

手順
① MahApps.Metro.IconPacksを選択
② インストールするプロジェクトにチェックを入れる
③ インストールする
 ![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627984/435fda5f-b6c2-04cf-cbed-5b6e6fc37e98.png)

# 2. IconPacks-Browserのインストール
下記のサイトからインストーラーがダウンロードできるのでIconPacks-BrowserをPCにインストールしてください。
https://apps.microsoft.com/detail/9nblggh3ztbp?hl=jp-US&gl=US

#### 起動してみる
起動すると下記の画面が開きます。使いたいアイコンをクリックし、コードをコピーして使います。
※FontAwesomeだけ、今回の方法では使用できませんでした。

![スクリーンショット 2024-05-02 165802.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627984/9e29c4b8-fe0d-15f7-0cc4-92dc384a16a0.png)

# 3. 使い方
- XamlファイルのWindowタグに「xmlns:Icon="http://metro.mahapps.com/winfx/xaml/iconpacks"」を追加する

```C#:MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
        // ・・・省略・・・
        xmlns:Icon="http://metro.mahapps.com/winfx/xaml/iconpacks" //←コレ
        // ・・・省略・・・
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        
    </StackPanel>
</Window>

```

- ソリューションのビルドを行う
![タイトルなし2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627984/7d6d7315-c167-ac71-267c-f1ef8e6ac2f7.png)

- IconPacks-Browserから使用したいアイコンのコードをコピペし、「iconPacks」→「Icon」に直す

例：
```C#
<iconPacks:PackIconMaterial Kind="Home" />    // ×
　　↓
<Icon:PackIconMaterial Kind="Home" />         // ○
```

全体のコード
```C#:MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
        // ・・・省略・・・
        xmlns:Icon="http://metro.mahapps.com/winfx/xaml/iconpacks" //←コレ
        // ・・・省略・・・
        Title="MainWindow" Height="450" Width="800">
        
    <StackPanel>
    
       <Icon:PackIconMaterial Kind="Home" />
       
    </StackPanel>
</Window>

```

すると・・・
![スクリーンショット 2024-05-02 171439.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627984/61018e0c-04e8-f823-dd97-8efb3fd25624.png)

アイコンが表示される。

下記のようにStyleを適用することもできます。

```C#:MainWindow.xaml
<StackPanel>
    <Icon:PackIconMaterial Kind="HomeMapMarker" Background="Blue" Height="50" Width="50" Foreground="White" Margin="50" Padding="5"/>
</StackPanel>
```

![スクリーンショット 2024-05-02 171754.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627984/c5d34c54-c1d9-a74b-b92a-e747f67cd1a4.png)

# 最後に
上記の方法を使えば、WPFアプリに簡単にアイコンを実装することができます。

ライセンスにはあまり詳しくないですが、MItライセンスで商用利用可能みたいです。
※ちゃんと調べたわけではないので、商用利用するときはちゃんと調べてください。
AWS CLF クラウドのコンセプト

# はじめに
AWS CLFにおいてクラウドとコンセプトの分野は24%ほどの配点割合を占めています。内容は概念的なものが多いため文章にて紹介します。
## クラウドのコンセプト
AWS CLFにおいて
このセクションの重要なキーワードとなるのは以下の通りです。
* コスト
* セキュリティ
* サーバーのサイジング
* 俊敏性
* スケーラビリティ
* 疎結合
* Design for failure
* 並列化
* AWS CAF

# コスト
AWSでは初期費用が不要かつ使用した分支払う従量課金制となっています。対してオンプレミスの場合は莫大な初期費用が必要となります。
# セキュリティ
AWSにおいてセキュリティはAWSおよび利用者の両方が管理する「責任共有モデル」というものが使われています。大雑把に言うとAWSはクラウド環境、利用者はクラウド内及び接続のセキュリティを管理することが義務付けられています。詳しい責任の所在はAWSのWebサイトでご確認ください(https://aws.amazon.com/jp/compliance/shared-responsibility-model/ )。
# サーバーのサイジング
サイジングとは利用するシステムおよびサービスの規模に合ったリソースを見積もるおよび用意することを意味します。オンプレミスでは厳密なサイジングが必要なのに対してAWSでは必要に応じてリソースを増減できるため厳密なサイジングは不要である。
# 俊敏性
AWSでは数分でITリソースの確保が可能です。また世界中にリージョンがあるため海外へのシステム展開が時短でできます。
# スケーラビリティ
スケーラビリティとは運用中のシステムを拡張、縮小させる能力を意味します。システムを拡張もしくは縮小することをスケーリングといい、リソースの数を変える水平スケーリングとリソースのスペックを変える垂直スケーリングの2種類が存在します。簡単に言い換えると量を調整するのが水平スケーリング、質を調整するのが垂直スケーリングです。
# 疎結合
疎結合とはシステム間の関係性が弱く、個々の独立性が高いことを意味します。疎結合システムもしくは疎結合アーキテクチャではシステム障害が起きてもその影響を局所化できるという利点がある。
# Design for failure
AWSにおいてDesign for failureとは故障を考慮し、高い可用性及び回復力を持つ設計を意味します。Design for failureの例としてシステムを複数のAZを使用してシステムを構築することが推奨されています。
# 並列化
並列化とは複数のリソースを用いて複数の処理を行うことを意味します。結果として処理速度や障害への耐性の向上につながります。
# AWS CAF
AWS CAFはクラウド導入フレームワークを意味します。AWS CAFを利用することには以下の利点があります。
* ビジネスリスクの軽減
* 環境、社会、ガバナンスに関するパフォーマンスの向上
* 収益の拡大
* 業務効率の向上
### クラウドトランスフォーメーションのジャーニー
AWS CAFにおいてクラウドトランスフォーメーションのジャーニー(クラウド導入の工程)は4つのフェーズで構成されています。
##### 構想(エンビジョン)
クラウドを導入するビジネス上の目標を設定しビジョン、ロードマップを策定します。
##### 調整(アラインメント)
クラウド導入のメリットを各ステークホルダーに伝えるなどの、クラウド導入に向けて組織内での調整を行います。
##### 起動(ローンチ)
起動フェーズではクラウド導入に必要な開発や導入作業を実施します。
##### スケール
スケールフェーズでは構想フェーズで設定した目標が達成できているか計測し、目標と差分があれば問題点の改善を行い目標達成を目指します。
### 6つのパースペクティブ
AWS CAFはクラウド導入および運用に役立つフレームワークを6つの視点(パースペクティブ)で提供しています。
##### ビジネス
ビジネスパースペクティブでは組織のビジネス目標およびクラウド戦略の加速を支援するためのフレームワークを提供しています。ビジネスパースペクティブの一般的なステークホルダーとしてCEO、CFO、COO、CIO、CTOなどがあげられます。
##### 人材
人材パースペクティブでは文化や組織構造に重点を置き、継続的な成長、学習、変化が通常となる組織へと進化できるよう支援するためのフレームワークを提供しています。人材パースペクティブの一般的なステークホルダーとしてCIO、COO、CTO、クラウドディレクター、複数部門に渡るリーダーなどがあげられます。
##### ガバナンス
ガバナンスパースペクティブでは組織の利益を最大化、変化に伴うリスクを最小化できるクラウドへの取り組みの調整を支援するためのフレームワークを提供しています。ガバナンスパースペクティブの一般的なステークホルダーとしてCIO、CTO、CFO、CDO、CROなどがあげられます。
##### プラットフォーム
プラットフォームパースペクティブではクラウドアーキテクチャの構築、既存のワークロードの近代化、新しいクラウドソリューションの導入を支援するためのフレームワークを提供しています。プラットフォームパースペクティブの一般的なステークホルダーとしてCTO、テクノロジーリーダー、アーキテクト、エンジニアなどがあげられます。
##### セキュリティ
セキュリティパースペクティブではデータやクラウドワークロードの機密性、完全性、可用性の実現を支援するためのフレームワークを提供しています。
セキュリティパースペクティブの一般的なステークホルダーとしてCISO、CCO、内部監査のリーダー、エンジニアなどがあげられます。
##### オペレーション
オペレーションパースペクティブではクラウドサービスがお客様のビジネスニーズを満たすレベルで提供することを支援するためのフレームワークを提供しています。オペレーションパースペクティブの一般的なステークホルダーとしてオペレーションリーダー、サイト信頼性エンジニア、情報技術サービスマネージャーなどがあげられます。
# 参考元、引用元
* https://aws.amazon.com/jp/cloud-adoption-framework/
* https://www.youtube.com/@AWS_course
* https://aws.amazon.com/jp/compliance/shared-responsibility-model/
Simulinkで一次のローパスフィルタを実装するだけ

# このページについて
Simulinkで一次のローパスフィルタを実装するだけのページです。
特に意味はありません。

# Simulinkモデル
こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/12a0d5d3-845b-c236-9663-721757d9c96e.png)

# 実行結果
実行結果は以下のような感じ。
フィルタゲインを0.05、処理周期を0.01[s]で設定してるので、時定数は0.2[s]になっている。
("フィルタゲイン = 処理周期 / 時定数"なのでね。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/1e76a30d-9a93-9c0a-10e6-72ecc23adf6b.png)


# 参考にしたページ

http://operalegend.blog.fc2.com/blog-entry-111.html
Permission denied (publickey)

### 事象
4月のサーバー管理の引き継ぎ後，サーバーにssh接続できなかった．

### 症状

・pingは通る
```
ping <サーバーipアドレス>
```
・telnetで確認するとポートも開いている
・systemctlでrestartしても直らず
・~/.ssh/authorized_keysを見ても問題ないように見える
・サーバー再起動でも直らず
・/etc/ssh/sshd_configを見ても直らず

### 原因
~/.ssh/authorized_keysのファイルが壊れていた．
具体的には，ファイルの先頭がREPLACEMENT CHARACTERになっていた．


### 診断方法
下記コマンドでauthorized_keysの中身を確認すると結果が返ってこない．
（ちなみに，投稿者はこのコマンドで結果が返ってこなかったとき，「まぁcatすれば結果返ってくるし問題ないかぁ」などと考えてしまったために解決する頃には半日過ぎていた）
```
cat .ssh/authorized_keys | grep rsa
```

### 解決方法
authorized_keysのファイルを作り直す．
ローカルHyper-V接続のための専用ユーザーを作り、ログオン時に自動でVMConnectを起動させるスクリプト



# 経緯
・さっくりとローカルVM接続だけの専用ユーザーを作りたい
・ただしRDPは使いたくない（VMConnectのメリットは後述します）
・のちのち共有PCモードやキオスクPCモードなどでもできるかを試したい

# 設計
・スクリプト1：Hyper-V管理者権限を持つユーザーを作成
・スクリプト2：VMconnectを実行
・スクリプト3：タスクスケジューラを作成し、ユーザーログオン時にPS1を実行
・すべてのユーザーが対象

# スクリプト1

```CreateHyperVAdmin.ps1
$username = Read-Host "新しいHyper-V管理者ユーザーのユーザー名を入力してください"
$password = Read-Host "新しいHyper-V管理者ユーザーのパスワードを入力してください" -AsSecureString

New-LocalUser -Name $username -Password $password -PasswordNeverExpires:$true
Write-Host "ユーザーアカウント '$username' が正常に作成されました。"

$confirm = Read-Host "'$username' を Hyper-V Administrators グループに追加しますか？ (Y/N)"
if ($confirm -eq "Y" -or $confirm -eq "y") {
    Add-LocalGroupMember -Group "Hyper-V Administrators" -Member $username
    Write-Host "ユーザー '$username' が Hyper-V Administrators グループに追加されました。"
} else {
    Write-Host "ユーザー '$username' は Hyper-V Administrators グループに追加されませんでした。"
}

$rdpUsers = Get-LocalGroupMember "Hyper-V Administrators" | Select-Object -ExpandProperty Name
$rdpUsers = $rdpUsers -replace '.*\\'
$rdpUsersInfo = $rdpUsers | ForEach-Object { [PSCustomObject]@{ Username = $_ } }

Write-Host "Hyper-V管理者のリスト:"
$rdpUsersInfo | Format-Table -Property Username

Pause

```

# スクリプト2
C:\Program Files\Scripts\vmconnect.ps1
などに保存します。スクリプトにコンパイルしたのは後々の開発バッファのためです。
```vmconnect.ps1
vmconnect localhost VM1
```

# スクリプト3

```CreateTask_for_VMConnect.ps1
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File `"`C:\Program Files\Scripts\vmconnect.ps1`""
$trigger = New-ScheduledTaskTrigger -AtLogOn
$principal = New-ScheduledTaskPrincipal -GroupId "Hyper-V Administrators" -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName "ConnectVMOnLogon" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description "標準ユーザーがログオンしたらVMConnect.exeを管理者権限で実行します。"

```

# 結果
これでHyper-V管理権限のあるユーザーがPCにログオンすると、VMConnectが自動実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b7c670e9-838b-f154-eb34-844b5448fca4.png)

# Why VMConnect over RDP?　ホワイジャパニーズ？

・こちらのページにRDPとVMConnectの違いが書かれていました。（10年前の記録を残して頂いているのはありがたいですね。）http://ayufishing.blog.fc2.com/blog-entry-14.html
・ネットワーク帯域を消費しないことや、最新バージョンだとウインドウサイズ変更で解像度がダイナミックに変更されるなどがあります。
・まずは使ってみることをお勧め致します。ユーザーエクスペリエンスはRDPより高いことが分かります。
・ちなみにVMConnectはHyper-Vコンソールのサブセットのため、Home版ではHyper-Vが使えませんので、Pro版以上のOSが必要となります。
templateでC3861

C++ の template をいろいろと試してみているのだけど，その途中で唐突に

> 識別子が見つかりませんでした

と言われて「ちょっと意味わかんないですね…」ってなった．

↓の `Deriv::F3()` がコンパイル通らない．
「 `empty` って何すか？」とのことだ．
仕方ないので試しに `F1()` とか `F2()` のように「いや，だからコレだよコレ」という感じで書いてやると何事もなかったかのように通る．

```C++
template< class T >
struct Base
{
    bool empty() const {    return true;    }
};


template< class T >
struct Deriv : public Base<T>
{
    bool F1() const {   return Base<T>::empty();    }   //OK
    bool F2() const {   return this->empty();   }   //OK
    bool F3() const {   return empty(); }   //C3861  'empty': 識別子が見つかりませんでした
};
```

基底クラスの public なメンバが見えないとか，そんなことってないだろう！？

何やら派生元が `Base<T>` という template な型であることが要因っぽいが……
こんなのでコンパイルエラーとか言われなかったような気がするんだよなぁ（←曖昧な記憶だけども）．

何なのコレ？

…ということで，頑張って検索してみたところ，どうやら「[/Permissive-（標準への準拠）](https://learn.microsoft.com/ja-jp/cpp/build/reference/permissive-standards-conformance?view=msvc-170)」というページに書かれている話が該当する模様．

> コンパイラに標準準拠モードを指定します。 このオプションを使用すると、コード内の準拠の問題を特定して修正し、より正確で移植性の高いものにすることができます。

とか書かれているので，「コンパイル通っていた（気がする）」という挙動の方がまちがい(?)というか　標準に準拠していなかった　ということか．

仕方ない．片っ端から `this->` って付けて回ることにするか．
P5.js 日本語リファレンス(clip)

このページでは[P5.js 日本語リファレンス](https://qiita.com/bit0101/items/91818244dc26c767a0fe) の clip()を説明します。

## clip()

### 説明文
clip()以降で描画される内容の一部をマスクする(覆い隠す)ための形状を定義します。

最初のパラメータ callback は、マスクを定義する関数です。コールバックで描画された形状はすべてマスク形状に追加されます。マスクは、clip() が呼び出された後に描画されるものすべてに適用されます。

2番目のパラメータである options はオプションです。 


invert: true }) のように、invert プロパティを持つオブジェクトが渡された場合、それはマスキング モードの設定に使用されます。 { invert: true } マスクを反転し、マスクされた形状に穴を作成します。 invert はデフォルトでは false です。

マスクは、push() 関数と Pop() 関数の間に含めることができます。これにより、マスクされた形状の後にマスクされていない形状を描画できるようになります。

### 構文
clip(callback, options);


### パラメタ

- callback
マスク形状を定義するための関数などを指定します。
- options  
`invert:false` : マスク形状で覆い隠す(デフォルト)
`invert:true` : マスクを反転する(falseで覆い隠していた部分のみを描画する)


### 戻り値

### 例

https://editor.p5js.org/bit0101/sketches/vjw27tA3E


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
path_helperは使いたくない。しかし、MANPATHは自動設定したい。。。

# 事の起こり
先日HomebrewでアプリケーションのUpdateついでに現在の状態が正常か確認する`brew doctor`コマンドを実行しました。すると、`Warning: /usr/bin occurs before /opt/homebrew/bin in your PATH.`という警告文と共に怒濤のメッセージが出力されました。。。:scream: :scream_cat: これは一大事と色々原因を探ってみたところ、.bash_profile内で宣言している環境変数に原因が有りそうだと突き止めました。しかし、どの宣言が原因なのかなかなか判明せず、時間を要しました。一旦全ての宣言を止めて再度brew doctorコマンドを実行すると正常に動作します。どこかで、PATH内の順番が書き換わっているのは確かですが、そんな宣言はした覚えが無いと思っていました。ところが、TeX関連の宣言で用いている`path_helper`が悪さをしていることが分かりました。よって今回はその対処方法を記事として残しておこうと思います。

* 参考

https://qiita.com/y-vectorfield/items/f326c150cee2d6108380#warning-usrbin-occurs-before-opthomebrewbin-in-your-path

# そもそもpath_helperの用途とは？
PATHやMANPATH(manコマンドで読み込むマニャルのPath)を生成します。特にMANPATHでは追加のファイルパスが追記されているので、完全に利用を停止することは難しそうです。

```bash: デフォルト状態
$ echo $MANPATH 
/opt/homebrew/share/man:
```

```bash: path_helper利用時
$ echo $MANPATH 
MANPATH="/usr/share/man:/usr/local/share/man:/opt/X11/share/man:/Library/TeX/Distributions/.DefaultTeX/Contents/Man:/Applications/Wireshark.app/Contents/Resources/share/man:/opt/homebrew/share/man:"
```

# 対処方法案1: 手動追記
手動で.bash_profileにMANPATHを宣言する方法です。以下を.bash_profileに追記します。

```bash
export MANPATH="/usr/share/man:/usr/local/share/man:/opt/X11/share/man:/Library/TeX/Distributions/.DefaultTeX/Contents/Man:/Applications/Wireshark.app/Contents/Resources/share/man:/opt/homebrew/share/man:"
```

しかし、この方法だと自動的に更新されないため、漏れが発生してしまいます。

# 対処方法案2: 自動追記(コマンドの組み合わせ)
コマンドを組み合わせて自動的にMANPATHを生成する様にしてみます。こうすれば、更新が有っても自動的に.bash_profile読み込み時に更新されます。

```bash
MANPATH=$(/usr/libexec/path_helper -s | grep MANPATH | awk -F'[;]' '{print $1}')
export MANPATH
```

# Homebrewでインストールしたアプリのエントリの追加
Homebrewでインストールを実施したアプリケーションのmanエントリも追加します。

```bash
MANPATH=$(/usr/libexec/path_helper -s | grep MANPATH | awk -F'[;]' '{print $1}')
MANPATH="$(brew --prefix)/share/man/:$MANPATH"
export MANPATH
```

これで無事brew doctorコマンドを実行しても警告は出なくなり、`Your system is ready to brew.`と表示される様になりました。めでたし。めでたし。

# Reference
https://qiita.com/sanriyochan/items/c4f8738ee1f16b318323

https://qiita.com/yamazon/items/563af1b485ff413d381f
クエリパラメータってなに？

「クエリパラメータ」というのは、さまざまな情報をWebサーバーに伝えるために"URL"に付け加える情報。例えば。。。
```
http://localhost:8000/?msg=hello
```
みたいに、?以降についてる部分がクエリパラメータ。
```
?変数名=変数の値
```
パラメータが複数ある場合は「&」でつないでいく。

:::note info
もそも「クエリ」とは？
そもそも「クエリ」というのは、検索をおこなう際の検索条件のことだ。

一般に、データベースや表で何らかの検索をおこなう場合は、「検索対象となる項目」と「検索キーワード」を指定する必要がある。

たとえば、Excelで作った社員名簿という表があると想像してほしい。社員の中から「鈴木」という「名字」の社員を検索したい場合は、「検索対象となる項目」に「名字」を指定し、「検索キーワード」に「鈴木」という文字列を指定する。この場合は、「名字＝鈴木」というのがクエリということになる。

この「名字＝鈴木」という検索をおこなう際の「名字」にあたるものことを「パラメータ（変数）」といい、一方、「鈴木」にあたる文字列のことを「パラメータ（変数）の値」という。
<引用文献>
impress, 「URLクエリパラメータ(クエリストリング)の意味とは。」, https://webtan.impress.co.jp/e/2012/04/26/12663　(2024年5月2日)
:::

## Djangoでクエリパラメータを使って、"Hello! World!"を表示させよう！
views.pyに次のコードを書いてみよう。
```
from Django.http import HttpResponse
def index(request):
   msg = request.GET["msg"]
   return HttpResponse(msg)
```
requestを引数に取っているが、このrequestとは？
そうです、HttpRequestというクラスのインスタンス。これは、クライアントがサーバにアクセスした際に、クライアント側の様々な情報を管理するもの。その中の、GETというのは、これは辞書的なもの。

## Webブラウザでアクセスしてみよう！
python manage.py runserverで、ローカルサーバを立ち上げて、アドレスを次のように打とう。
```
http://localhost:8000/書いた場所のフォルダ/?msg=?msg=hello!%20World!
```
クエリパラメータをURLに含める際には、値をダブルクォーテーションで囲む必要はありません。クエリパラメータは単なるテキストだから親切心で囲わなくてもいい！ここで %20 は、スペースをURLエンコードしたもの。
結果がこれです！
↓↓↓
![スクリーンショット 2024-05-02 163741.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779281/038c2f2c-c720-f739-f27e-02da51f6c0c0.png)
SwiftでSOLID原則（2a/3）

## はじめに
前回の記事[「SwiftでSOLID原則（1/3）」](https://qiita.com/generosity-naman/items/2ca9e5b731463e6457fc) では、ソフトウェアデザインの中心である SOLID 原則 の概念を紹介し、特に「単一責任の原則」（SRP）について詳しく解説しました。この記事では、 オープン/クローズドの原則（OCP） に関して、Swiftを使った例で、紹介したいと思います。

## オープン/クローズドの原則（OCP）
オープン/クローズドの原則は、「ソフトウェアのエンティティは、拡張には開かれ、変更には閉じているべき」と提唱しています。つまり、機能を追加したり改善する際、既存のコードを変更せずに対応できるようにモジュールを設計することが理想です。

### 概念的な例：
オープン/クローズドの原則は、建物の追加建築と似ています。新しい機能を追加したいとき、既存の構造物を壊すことなく、新しい部屋やブロックを加えられることが望ましいです。これにより、全体の構造が変わらず、新しい部分を追加するだけで新機能が実現されます。

### Swiftでの実例：
例えば、幾何学的な形状を表現する Shape クラスがあるとします。新しい形（例：三角形や楕円）を追加したい場合、既存のShapeクラスのコードを直接変更するのではなく、新しいサブクラスを作成して追加機能を実現します。これはコードを拡張可能にし、バグの発生を最小限に抑える手法です。
では二つの例を見てみましょう
#### 例１:
```swift
class Shape {
    enum ShapeType {
        case rectangle, triangle
    }
    
    var type: ShapeType
    var width: Double = 0
    var height: Double = 0
    var base: Double = 0

    init(type: ShapeType) {
        self.type = type
    }

    func area() -> Double {
        switch type {
        case .rectangle:
            return width * height
        case .triangle:
            return 0.5 * base * height
        }
    }
}

// 使用例
let rectangle = Shape(type: .rectangle)
rectangle.width = 10
rectangle.height = 5

let triangle = Shape(type: .triangle)
triangle.base = 8
triangle.height = 6

print("Rectangle area: \(rectangle.area())")
print("Triangle area: \(triangle.area())")

```
&ast;&ast;解説:このコードでは、`Shape` クラスが形状のタイプ (`ShapeType` 列挙型) を管理しており、`area()` メソッドで形状に応じた処理を行っています。新しい形状（例えば、円や正方形）を追加したい場合、`ShapeType` と `area()` のコードを修正しなければならず、OCPに反する設計です。コードを直接変更するたびに、バグを引き起こすリスクも増えます。

#### 例２:

```swift
// 定義されたShapeプロトコル
protocol Shape {
    func area() -> Double
}

// 四角形のサブクラス
class Rectangle: Shape {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    func area() -> Double {
        return width * height
    }
}

// 新しい形状を追加（既存コードに影響なし）
class Triangle: Shape {
    var base: Double
    var height: Double

    init(base: Double, height: Double) {
        self.base = base
        self.height = height
    }

    func area() -> Double {
        return 0.5 * base * height
    }
}

// 使用例
let shapes: [Shape] = [
    Rectangle(width: 10, height: 5),
    Triangle(base: 8, height: 6)
]

for shape in shapes {
    print("Shape area: \(shape.area())")
}
```
&ast;&ast;解説: この例では `Shape` プロトコルを使用して、異なる形状クラス（`Rectangle` や `Triangle`）の面積を計算するための共通インターフェースを提供しています。新しい形状を追加しても、既存のコードを変更する必要がありません。

### 適用性：
OCPは、再利用可能で拡張可能なソフトウェアコンポーネントを設計する際に特に役立ちます。機能追加が求められるプロジェクトにおいて、既存のコードを保護しつつ拡張するための有効な手法です。

### 実装方法：
OCPを実現するために、インタフェース、プロトコル、または抽象クラスなどを用いて契約を定義します。この契約に基づく新しいクラスを作成し、OCPに従い、既存のコードの変更を避けながらも機能を追加します。

### メリット：
- コードの再利用性が向上し、コードを変更することで発生する潜在的なバグのリスクが低減されます。
- ソフトウェアの保守性が向上します。

### 留意点：
この原則を適用するには、設計時点で先見の明が必要です。また、過度な抽象化は複雑さを招く可能性があるため、OCPの使用が適切かを見極めることが重要です。

## 結論:
ここまでで、SOLID原則の二つの重要な原則である「単一責任の原則」と「オープン/クローズドの原則」について掘り下げて学びました。次回の記事では、「リスコフの置換原則」 に注目し、Swiftでの具体的な実装例とともに、その効果とメリットを紹介します。次の記事まで、ハッピーコーディング！
GWに考えるキャリアのレバレッジについて

結論、キャリアの初期にレバレッジと複利効果を得るために懸命に働くことが重要だと思ってます。

若い時はプライベートを犠牲にすることなく、バランスを保つことも重要です。しかし、その時期に努力することで得られる経験とスキルは、その後のキャリアにおいて大きな財産となります。

**キャリアの初期に努力することのメリット**

* **幅広い知識とスキルの習得:** キャリアの初期は、スポンジのように新しいことを吸収しやすい時期です。この時期に多くの仕事をこなすことで、幅広い知識とスキルを身につけることができます。これは、その後のキャリアにおいて非常に役立ちます。
* **人脈の形成:** 様々な仕事に挑戦することで、様々な人と出会う機会が増えます。人脈は、その後のキャリアにおいて大きな力となります。
* **自信の向上:** 仕事をうまくこなすことで、自信がつきます。自信は、仕事をする上でとても重要です。
* **複利効果:** キャリアの初期に努力しておけば、その後のキャリアにおいてより多くの成果を上げることができます。これは、複利効果のようなものです。

**キャリアの初期を充実させるためのアドバイス**

* **積極的に仕事に挑戦する:** 与えられた仕事だけでなく、積極的に新しい仕事に挑戦しましょう。
* **わからないことは積極的に質問する:** わからないことがあれば、先輩や上司に積極的に質問しましょう。
* **先輩から学ぶ:** 先輩の仕事ぶりを観察し、積極的に学びましょう。
* **人脈を広げる:** 積極的に人と交流し、人脈を広げましょう。
* **自己研鑽を怠らない:** 常に新しい知識とスキルを身につけるために努力しましょう。

キャリアの初期は、その後の人生を大きく左右する重要な時期です。この時を有効活用して、ぜひ充実したキャリアを築いてください。

**レバレッジと複利効果を最大限に活用する**

キャリアの初期に努力することで得られる経験とスキルは、レバレッジと複利効果によってさらに増幅されます。

* **レバレッジ:** キャリアの初期に得た知識とスキルは、その後のキャリアにおいてより多くの成果を生み出すことができます。これは、レバレッジの効果に似ています。
* **複利効果:** キャリアの初期に得た経験とスキルは、時間をかけてさらに成長していきます。これは、複利効果の効果に似ています。

つまり、キャリアの初期に努力することで、その後のキャリアにおいてより多くの成果を上げることができるのです。

**まとめ**

キャリアの初期にレバレッジと複利効果を得るために懸命に働くことは、決して無駄ではありません。むしろ、その後のキャリアにおいて大きな成果を上げるために必要な投資と言えるでしょう。ぜひ、この貴重な時期を有効活用して、充実したキャリアを築いてください。
# 電池で駆動するNeoPixel制御ボードのサンプルプログラム②

- # RP2040-ZEROを使ってNeoPixelを制御するサンプルプログラム②です。
  
- ### サンプルサンプルプログラム内容
  6x6に並んだNeoPixelの指定したLEDを光らせる。
  
- ### プログラム環境
　ArduinoIDE バージョン：2.2.1
　使用ライブラリAdafruit NeoPixel Library 1.12.0

  
- ### ハードウェアの主な仕様
　マイコン:PR2040-ZERO
　NeoPixel接続ピン　GPIO8
　乾電池2本でお外へ持ち出し可能。

- ### サンプルプログラム

``` C++:make39_neopixel17.ino

#include <Adafruit_NeoPixel.h>

#define LED_PIN    8  // NeoPixelのデータピン
#define LED_COUNT 36  // LEDの総数 (6x6)
#define LED_WIDTH  6  // LEDマトリクスの幅
#define LED_HEIGHT 6  // LEDマトリクスの高さ
#define LED_BRIGHTNESS 24 // LEDの明るさ (0-255)

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(LED_BRIGHTNESS); // 明るさの設定
  strip.show(); // 初期化時は全てのLEDを消灯する
}

void loop() {
  // 例：LED配列の(2, 3)の位置にLEDを点灯させる
  int x = 2;
  int y = 3;
  int ledIndex = getLedIndex(x, y);
  if (ledIndex != -1) {
    strip.setPixelColor(ledIndex, 255, 255, 255); // (R, G, B) の色指定
    strip.show();
  }
  delay(1000); // 1秒間LEDを点灯させる
}

// (x, y) 座標からLEDのインデックスを取得する関数
int getLedIndex(int x, int y) {
  if (x >= 0 && x < LED_WIDTH && y >= 0 && y < LED_HEIGHT) {
    return y * LED_WIDTH + x; // 座標からインデックスを計算
  }
  return -1; // インデックスが範囲外の場合は-1を返す
}

```

- ### このプログラムを作成した時の考え方

データピンは、マイコンのGPIO8ピンとNeoPixelが接続してめ決定しています。

```c++
#define LED_PIN    8  // NeoPixelのデータピン
```

NeoPixelの数を決めています。

```c++
#define LED_COUNT 36  // LEDの総数 (6x6)
```

マトリックスの縦横のLED数を指定しています。
LEDを光らせる場所を、横を0から幾つ、縦に0から幾つといった
指定をするために定義しています。

```c++
#define LED_WIDTH  6  // LEDマトリクスの幅
#define LED_HEIGHT 6  // LEDマトリクスの高さ
```

NeoPixelの明るさを指定します。
MAX値は255ですが、USBの供給能力を考慮すると127以下での使用がベターです。
昼間の日の下でなければ十分な明るさになります。
部屋の中で使用するならば16から32ぐらいで十分な明るさがあります。

```c++
#define LED_BRIGHTNESS 24 // LEDの明るさ (0-255)
```

NeoPixelに信号を送るときの命令です。
```c++
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
```

光らせる場所を指定する。
このサンプルプログラムの場合、
　左上から0, 1, 2と数えて2番目
　左上から0, 1, 2, 3と数えて3番目
 を指定したところが光ります。

```c++
  // 例：LED配列の(2, 3)の位置にLEDを点灯させる
  int x = 2;
  int y = 3;
  ```

![make39_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/7f2e82d2-4031-cb20-6534-94c50ed1f893.jpeg)


上で設定したx, yの位置指定をLEDの順番指定「ledIndex」に変換します。
LEDは、RED, GREEN, BLUEで指定しています。
RED, GREEN, BLUEは、255に指定しているのでLEDが白色で光ります。
```c++
  int ledIndex = getLedIndex(x, y);
  if (ledIndex != -1) {
    strip.setPixelColor(ledIndex, 255, 255, 255); // (R, G, B) の色指定
    strip.show();
  }
```


これを踏まえて(1, 1) R=255, G=0, B=0とすると
(2, 2)が赤色に光ります。

```c
  int x = 1;
  int y = 1;
  int ledIndex = getLedIndex(x, y);
  if (ledIndex != -1) {
    strip.setPixelColor(ledIndex, 255, 0, 0); // (R, G, B) の色指定
    strip.show();
  }
```


![make39_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/fe72e126-6c31-c31b-ce6c-bec026959d72.jpeg)
Virtaulboxにインストールしたubuntu-serverにteratermで接続ができなかった原因について

Virtualboxにubuntu-serverをインストールしてteratemで接続しようとしたら接続できなかったり、pingで外部にアクセスできなかったりしたので設定を見直してみました。

## 原因
ホストオンリーアダプターのGatewayの設定をしてしまったことが原因だったようです。
以下のページが参考になりました。
https://teratail.com/questions/bt10wqo0pyg5h1

>ホストオンリーアダプターはローカルネットワーク用の仮想NICであり、ここから外部ネットワークに通信はしませんので、gateway等の設定はしません。gateway設定は、enp0s3（NAT）側でDHCPで設定されているはずです。
SSH 多段接続（二つ以上）




:::note info
LOCAL ->  user1@XXX.XXX.XXX.XXX -> user2@YYY.YYY.YYY.YYY -> user3@ZZZ.ZZZ.ZZZ.ZZZ にアクセスしたい場合
:::

```bash
# SSH 多段接続
ssh -J user1@XXX.XXX.XXX.XXX,user2@YYY.YYY.YYY.YYY user3@ZZZ.ZZZ.ZZZ.ZZZ
```
XcodeでwatchOS 10.4 Not Installedと表示してしまう問題

# 結論
PC再起動すれば改善しましたが、それだと記事的に少なすぎるので、Macを再起動して動いたまでの過程を書き出してみました。

## Xcodeを開いてみた

前回からの続き↓↓
[AppleWatchで実機ビルド](https://qiita.com/Masa_sa/items/a7f418b3319451e349b1)

AppleWatchで実機ビルドできるようになってから日を置いて再度プロジェクトを立ち上げてみたら、'watchOS 10.4 Not Installed'となっていた…（*Xcodeは15.3を使用）

<img width="400" alt="watchos-not-installed" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/779616/ddecd574-0b84-3256-df2a-8ae1d2ea5e52.png">


## とりえあずGetを押してみた

'watchOS 10.4 Not Installed' の下にある Get を押下。
Simulatorのインストールが始まりました。

Simulatorのインストールが完了しても、表示は消えず…
前回までは動いていたのに、、

## ビルドボタンを押してみた
ふと左上のビルドボタンを見てみると、斜線のボタンになっていました。

<img width="300" alt="build-button" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/779616/f6b36ed5-3fef-cc7d-2e55-0bd1629e71ec.png">

とりあえずポチッと押してみたところ、以下のポップアップが表示。

<img width="400" alt="xcode-popup" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/779616/f5287844-61da-6251-7fb7-46985aeb48a9.png">

え〜、、さっきインストールしたのに😮‍💨
'Download & Install'を押してみても、Simulatorがインストール完了しているポップアップが表示しただけでした

## Xcodeを再起動

再起動してもダメでした。'watchOS 10.4 Not Installed'のまま…

## Macを再起動して解決

困った時の再起動を実施。
出だしで書いちゃいましたが、再起動したら改善しました。
REST APIを作成してみる

# 概要

本記事は [AWSでWebアプリを構築してみる](https://qiita.com/ti_and6id/items/9670ee60965a4d10bec7) シリーズの5回目の記事です。
前回の記事は [こちら](https://qiita.com/ti_and6id/items/d329ce5e9dc838563d7f)。

# REST APIを作成してみる

## 1. Lambda 関数の作成

1. マネジメントコンソールからLambdaを開き、「関数の作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/f4702244-d306-223c-c187-e1469e992aac.png)
 
1. 「一から作成」を選択

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/ebbab1b5-1cab-6815-ca1f-8ba57f7bacf3.png)

1. 基本的な情報を入力して関数を作成

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/f111b3b4-bb16-a9ec-387a-ad473c0c8e5f.png)

1. 作成した関数でコードソースを編集してデプロイ

    ここではダミーデータとしてユーザーの一覧を返すようにしてみます。
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/a5773bb4-1003-4973-b9b3-f44fc56e63eb.png)
    ```
    export const handler = async (event) => {
      const response = {
        statusCode: 200,
        body: JSON.stringify([{
          name: "森 聡",
          age: 45
        }, {
          name: "井上 祐輔",
          age: 20
        }, {
          name: "高橋 智明",
          age: 35
        }, {
          name: "村田 正人",
          age: 53
        }, {
          name: "石井 俊輔",
          age: 37
        }]),
      };
      return response;
    };
    ```

## 2. API Gateway で REST API の作成

1. マネジメントコンソールからAPI Gatewayを開き、「APIを作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/4abe16e2-76a1-72a2-4d1a-f74b5e8cfbb0.png)

1. REST APIの「構築」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/038b477d-1d22-09a8-d794-ba2ea5131715.png)

1. 「新しいAPI」とし、API名などを設定し、「APIを作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/5e9556e4-3a6b-22df-8742-ae21a4350cf1.png)

## 3. API にエンドポイントの設定を行う

1. メソッドの「メソッドの作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/06bc72b2-934f-cb15-7109-bbd32d2d6663.png)

1. メソッドの詳細を設定してメソッドを作成する

    Lamadaの作成ではユーザー一覧を取得するものを用意したため、メソッドタイプは「GET」、統合タイプでは「Lambda関数」を選択し、Lambdaプロキシ統合をONにして対象となるLambda関数を選択します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/0f8959c7-dbab-1482-dbd0-b4ca5dc11a85.png)


1. APIをデプロイする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/539833ae-8783-043a-5048-bd0754d4b0dc.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/50d6ed72-4253-5202-e5e3-76f1f094cc36.png)

## 4. API をテストする

1. 作成したAPIのリソースのテストタブから「テスト」を行う

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/106a0d2b-eda9-da50-cd22-a1bb891232d5.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/f32615e1-759e-8aa8-56f2-be2509f979f4.png)

    GETなので作成したステージに記載されているURLから呼び出してもOK
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/3196ce20-adf9-c2d8-1726-69f2d34bdbf0.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/c84821c0-5ebe-0548-c709-0cd539a6b336.png)
Python文法まとめ【while】

# はじめに
Pythonの基礎的なことをまとめています。
Google Colabで実行できます。
[Colabの使い方(Python.jp)](https://www.python.jp/train/experience/colab.html "Python.jp 入門講座")

# 繰り返し処理
~~~Python:サンプル
stamp = 0
print('スタンプラリーを開催します。現在のスタンプは', stamp, '個です。')
while stamp < 5:
  stamp += 1
  print('スタンプを', stamp, '個押しました。')

print('おめでとうございます、スタンプが', stamp, '個集まりました！')
~~~
`stamp < 5`は、変数の値が5よりも小さいことを条件としています。
`stamp += 1`は、変数に1を足す式です。※
上記のコードでは`stamp`の値が`5以下`の時、
繰り返し`1`を足しています。

~~~:実行結果
スタンプラリーを開催します。現在のスタンプは 0 個です。
スタンプを 1 個押しました。
スタンプを 2 個押しました。
スタンプを 3 個押しました。
スタンプを 4 個押しました。
スタンプを 5 個押しました。
おめでとうございます、スタンプが 5 個集まりました！
~~~

~~~
while 条件式:
  処理
~~~
が基本形です。

※
`stamp = stamp + 1`と同じ意味です。
`=`は数式とは異なり、両辺が等しいという意味ではありません。
`右辺`を計算し、`左辺`へ代入する処理をあらわしています。

#### ifと組み合わせる
~~~Python:応用
stamp = 0
print('スタンプラリーを開催します。現在のスタンプは', stamp, '個です。')
while stamp < 5:
  stamp += 1
  print('スタンプを', stamp, '個押しました。')
  if stamp == 4:
    print('残り1個です！')

print('おめでとうございます、スタンプが', stamp, '個集まりました！')
~~~

# おわり
お役に立てたら幸いです。
rsyncで同期しているディレクトリ中、今どこのファイルが書き込まれているかをチェックする

du -d1 /home/directory > /tmp/1 ; sleep 5 ; du -d1 /home/directory/ > /tmp/2 ; diff /tmp/1 /tmp/2

ゴミを残したくなければ、rm /tmp/1 /tmp/2　を追加してもよいかも。
また、全ディレクトリを掘りたいのであれば、-d1 オプションを外せばよいかと。
※もっとも、環境や状況により -dNについては適宜調整。
P5.js 日本語リファレンス(beginClip/endClip)

このページでは[P5.js 日本語リファレンス](https://qiita.com/bit0101/items/91818244dc26c767a0fe) の beginClip()〜endClip()を説明します。

## beginClip()〜endClip()

### 説明文
endClip()以降で描画される内容の一部をマスクする(覆い隠す)ための形状を定義します。

### 構文
beginClip(options);
　ここにマスク形状を定義する
endClip();


### パラメタ

- options  
`invert:false` : マスク形状で覆い隠す(デフォルト)
`invert:true` : マスクを反転する(falseで覆い隠していた部分のみを描画する)


### 戻り値

### 例

https://editor.p5js.org/bit0101/sketches/E4nKra-8A


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
SSL/TLS についてメモ

SSL/TLSについて知識が曖昧だったのでメモ

# SSL/TLSとは
TLS/SSL は、インターネット上での通信を保護するための**暗号化プロトコル**

### 役割
- 通信内容の暗号化
    - 送受信されるデータが暗号化されることで、盗聴や改ざんから保護される
- サーバー認証
    - サーバの証明書を検証することで、偽装されたサーバとの通信を防ぎ、なりすまし攻撃から保護される

# 処理の流れ
1. クライアントが Web サーバに HTTPS でアクセスすると、クライアントと Web サーバ間で TLS/SSL **ハンドシェイク**と呼ばれるプロセスが行われる
2. ハンドシェイクでは、以下の手順が行われる
    - クライアントは、利用可能な暗号化アルゴリズムとハッシュ関数のリストを送信
    - サーバは、クライアントと共通の暗号化アルゴリズムとハッシュ関数を選択
    - サーバは、証明書を送信し、クライアントはその有効性を検証を実施
    - クライアントとサーバは、共有秘密鍵を生成
3. ハンドシェイクが完了すると、通信内容は共有秘密鍵を使って暗号化され、安全に送受信される

### 勘違いしがちなところ
NginxやApacheはSSL/TLSの設定や管理をしているのみで、実際にSSL/TLSを動かしているのではない。

# 動作確認
HTTPS通信において、サーバーはクライアントに証明書の情報を返却する。
実際にAPIを実行して、レスポンスに証明書の結果が含まれることを確認

```bash
curl -vS https://www.example.com
```

-v: 詳細な情報を表示
-S: ヘッダーのみを表示

```bash
* Connected to www.example.com (93.184.215.14) port 443 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: C=US; ST=California; L=Los Angeles; O=Internet�Corporation�for�Assigned�Names�and�Numbers; CN=www.example.org
*  start date: Jan 30 00:00:00 2024 GMT
*  expire date: Mar  1 23:59:59 2025 GMT
*  subjectAltName: host "www.example.com" matched cert's "www.example.com"
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
*  SSL certificate verify ok.
* using HTTP/2
* h2 [:method: GET]
* h2 [:scheme: https]
* h2 [:authority: www.example.com]
* h2 [:path: /]
* h2 [user-agent: curl/8.1.2]
* h2 [accept: */*]
* Using Stream ID: 1 (easy handle 0x12e811400)
> GET / HTTP/2
> Host: www.example.com
> User-Agent: curl/8.1.2
> Accept: */*
>
< HTTP/2 200
< age: 540655
< cache-control: max-age=604800
< content-type: text/html; charset=UTF-8
< date: Thu, 02 May 2024 00:52:14 GMT
< etag: "3147526947+ident"
< expires: Thu, 09 May 2024 00:52:14 GMT
< last-modified: Thu, 17 Oct 2019 07:18:26 GMT
< server: ECAcc (sac/2533)
< vary: Accept-Encoding
< x-cache: HIT
< content-length: 1256
...
```


```bash
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
```

ハンドシェイクプロセスのログがある！

```bash
*  SSL certificate verify ok.
```

SSL認証が通っていることが確認できた！

実際にコマンドを実行してみることで、ハンドシェイクが確立→認証→リクエストの送受信されることが理解できた。
LaTeX+VSCode環境構築(MacOS)


# はじめに
VSCodeでのLaTeX環境構築についてのまとめです。OSはMacです。

# MacTeXインストール
[Homebrew](https://brew.sh/ja/)から[MacTeX](https://tug.org/mactex/)をインストールします。Homebrewのインストール方法は[こちら](https://qiita.com/zaburo/items/29fe23c1ceb6056109fd)の方の記事をご覧ください。

【手順】

1. ターミナルを開いてMacTeXをGUIなしでインストール
    ```zshrc
    brew install --cask mactex-no-gui
    ```
    <br>
    


2. Macのシェル環境（zsh）の設定ファイルである.zshrcにインストールされた実行ファイルのパスを追加する
    ```zshrc
    export PATH=/usr/local/texlive/2024/bin/universal-darwin:$PATH
    ```
    <br>

3. シェルの設定ファイルを再読み込みし、パスが通っているか確認
    ```
    source ~/.zshrc
    latexmk --version
    ```

<br>
<details>
<summary>パスが通らない場合</summary>

`export PATH=/usr/local/texlive/2024/bin/universal-darwin:$PATH`の2024の部分が正しいかを確認します。ここにはインストールされたTex Liveのバージョンが入ります。

【手順】

1. インストールされたバージョンのディレクトリを確認
  ```zshrc
  ls /usr/local/texlive/
  ```

2. 下記のようにインストールされたバージョンのディレクトリを確認できる

  ```
  % ls /usr/local/texlive/
  2024		texmf-local
  ```

</details>



# VSCodeインストール

[https://code.visualstudio.com/download](https://code.visualstudio.com/download) からダウンロードしてください。

# LaTeX Workshopインストール

[こちら](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop) からインストールを押して、VSCodeに遷移後、VSCode上でインストール。

![latex_workshop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783005/253b409b-e202-fec2-013a-5786b16020db.png)

LaTeX WorkshopはVSCode上でLaTeXのビルド、PDFプレビューやコードスニペット等を持つ拡張機能です。機能については[こちら](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop#:~:text=and%20common%20issues-,Features%20(Taster),-This%20is%20not)。
[JavaScript] オブジェクト、プロパティ、メソッドについて

# まとめ

#### オブジェクトとは
> オブジェクト指向プログラミングにおいて、プログラム上の手続きの対象を抽象化する概念である。
※[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0))

#### プロパティとは 
> 多くの場合データ構造と関連付けられた属性を記述する、オブジェクトの特性です。
※[mdn web docs](https://developer.mozilla.org/ja/docs/Glossary/property/JavaScript)

#### メソッドとは
> オブジェクト指向プログラミング言語において、あるクラスないしオブジェクトに所属するサブルーチンを指す。
※[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%A6))

# 目次
- [オブジェクトとは](#オブジェクトとは)
- [プロパティとは](#プロパティとは)
- [メソッドとは](#メソッドとは)

# オブジェクトとは
- 「対象・物」＝ プログラミング言語で操作ができるデータ
- Ex.：HTML内のタグ、属性、値、文書（Document）

~~~index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja-JP">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <title>タイトル</title>
  </head>

  <body>
    <div>
      わたしは<span style="font-size:24px; color:#FF0000">文書</span>です。
      <img src="http://hakuhin.jp/test.jpg" alt="画像">
    </div>

  </body>
</html>
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/69b3291d-d089-1bd8-0881-3af747745e6a.png)

#### 解説
- `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">`：ドキュメント
- `<body></body>`や`<head></head>`：ドキュメント
- jsはhtmlを読み込むと、html内のオブジェクトをDOMオブジェクトとして認識する

# プロパティとは
- オブジェクトに関連付けられた情報やデータ

~~~index.js
const person = {
  name: "Yamamoto Taro",
  age: 28
};
// ドット記法でアクセス
console.log(person.name); // 出力: Sato Shinji
// ブラケット記法でアクセス
console.log(person["age"]); // 出力: 28
~~~

#### 解説
- `name`や`age`はプロパティ名
- `"Yamamoto Taro"`や`28`はプロパティの値

# メソッドとは
- オブジェクトに関連付けられた関数

~~~index.js
const person = {
  name: "Sato Shinji",
  greet: function {
    console.log("Hello, my name is " + this.name + ".");
  }
};
person.greet(); // 出力: Hello, my name is Sato Shinji.
~~~

#### 解説
- `greet: function {console.log("Hello, my name is " + this.name + ".");}`がメソッド（関数）

# 参考リンク
- [JavaScriptのオブジェクトとは？基本と使い方のコツを３分で解説](https://it-biz.online/web-design/object-2/)
- [ドキュメントオブジェクトモデル(DOM)について](https://hakuhin.jp/js/dom.html)
Mavenでライフサイクル構成でカバーされていないプラグインの実行を解決する


Eclipseで Maven で tomee-webapp-archtype でMavenプロジェクトを作成すると、以下のようなエラーが出力された。
```
ライフサイクル構成でカバーされていないプラグインの実行: org.apache.openjpa:openjpa-maven-plugin:3.2.2:enhance (実行: enhancer, phase: process-classes)`
```

調べると、同じような事象が発生しており、```pom.xml```の ```plugins```タグを```pluginManagement```タグで囲うことで解決できたとのことで、試したところ解決した。

```xml:pom.xml
<build>
    <pluginManagement> ←このタグを追加
        <plugins>
            <plugin> ... </plugin>
            <plugin> ... </plugin>
                  ....
        </plugins>
    </pluginManagement> ←このタグを追加
</build>
```

参照したサイトはこちら。

https://kobe-systemdesign.work/2020/09/29/java%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E6%A7%8B%E6%88%90%E3%81%A7%E3%82%AB%E3%83%90%E3%83%BC%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%97%E3%83%A9/
分割キーボードを購入したので、キーマッピングを設定した

分割キーボードがよいという噂を聞いたので、Amazonで購入しました。
[Mistel Barocco MD600v3 RGB Classic Black 英語US配列 62キー ブラック Cherry MX RGB 茶軸 MD600-BUSPDAAT3](https://www.amazon.co.jp/MiSTEL-BAROCCO-%E3%83%A1%E3%82%AB%E3%83%8B%E3%82%AB%E3%83%AB%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89-PBT%E3%82%AD%E3%83%BC%E3%82%AD%E3%83%A3%E3%83%83%E3%83%97-MD600-PJPPSGAA1/dp/B01KN6LBDU/ref=cm_cr_arp_d_product_top?ie=UTF8&th=1)
日本語配列のものと間違って英字配列のものを購入してしまったのですが、入力モード切替で日本語入力にすることができたので、ギリギリセーフでした。

## 早速スクリプト
```
#NoEnv  ; 他の環境変数に依存しない設定
SendMode Input  ; より高速で信頼性の高い入力モードを設定

; スペースキーと特定のキーの組み合わせでの動作
Space & j::Send, {Left}
Space & k::Send, {Down}
Space & l::Send, {Right}
Space & i::Send, {Up}
Space & u::Send, {Backspace}
Space & f::Send, {Space}
Space & g::Send, {tab}
Space & d::Send, {Delete}
Space & h::Send, {Home}
Space & sc027::Send, {End}
; Space + O と Shift + Space + O の動作を区別するスクリプト

~Space & o::
    if (GetKeyState("Shift", "P")) {
        Send, +{Enter}  ; Shift + Enter を送信
    } else {
        Send, {Enter}  ; 通常の Enter を送信
    }
return
; Spaceキー単独でのアクションは無効化
Space::return


#UseHook

; Space + Q で "!" を入力
Space & q::Send, {Raw}!

; Space + W でダブルクォーテーションを入力
Space & w::Send, {Raw}""

; Space + E で "#" を入力
Space & e::Send, {Raw}#

; Space + R で "$" を入力
Space & r::Send, {Raw}$
```

SpaceKey＋いろいろなキーで矢印やらなんやらを設定しています。

#### 解説
`#NoEnv`は、スクリプトが外部の環境変数に依存しないように設定するためのものです。これにより、スクリプトの動作がより予測可能になります。
SendMode Input は、キー送信の方法としてInputを選択しています。これはより高速で信頼性の高い入力方法です。

スペースキーと別のキー（`j, k, l, i, u, f, g, y`）の組み合わせによって特定のキー入力を行います。例えば、`Space & j` は左矢印キー、`Space & k` は下矢印キーとして機能します。
`Space & f::Send, {Space}` は、スペースキーとfキーの組み合わせでスペースを入力するためのマッピングです。

スペースキーとoキーが同時に押されたときの動作を定義しています。Shiftキーが同時に押されていれば、`Shift + Enter`を送信し、そうでなければ通常のEnterを送信します。

スペースキーと特定の文字キー（`q, w, e, r`）の組み合わせで特殊文字（`! ", #, $`）を入力するためのものです。
`{Raw}` モードを使用して、文字がそのまま（エスケープされずに）送信されるようにしています。

#### というわけで

このキーボードには物理的にLayerを使用してキーマッピングを設定できるのですが、それを使用せずAutoHotKeyですべて設定しました。

AutoHotKeyの設定方法は以下を参照。

https://musikirin.com/post/2017/10/30/mistel-barocco-md600-3/
https://qiita.com/mugiajinoocha/items/499040fa6751487e009b

物理的に設定したい場合参考となりそうな記事
https://qiita.com/Takuan_Oishii/items/0f7a0d278980265b69a5
GW中にぶれぶれの動画を撮ってしまったら、手軽にGoogle Colabで動画の手振れ補正

## 0.初めに

私は非エンジニアのドシロウトです。

GW連休中に手振れ補正し忘れて、アクションカメラでぶれぶれ動画を撮ってしまった方に手軽にGoogle Colabで動画の手振れ補正する方法をご紹介します。

:::note alert
**【重要】１分以下程度の短い動画を補正する場合のみお試しください。**
ファイルが大きくなると「ファイルのアップロード（元動画）」や「ffmpgで手ぶれ補正」に**非常に時間がかかります。**

１分を超える場合はローカルでやったほうが良いです。
私が試した限りでは元動画４分３２秒の手ぶれ補正は１時間以上でした。
:::

:::note info
**ローカルでも同じことはできます。**
ローカルで実施される方は私がもともと参考にした以下の記事の通りにやると良いと思います。

[ffmpeg によるバイク走行動画のスタビライズ(手ぶれ補正)](https://dyama.org/2019/01/ffmpeg-%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B9%E3%82%BF%E3%83%93%E3%83%A9%E3%82%A4%E3%82%BA/)
:::

## 1.どの程度手振れ補正できるのか

実際にColabでやってみた結果比較が以下です。
左が元の動画、右が補正後の動画です。、

<iframe width="560" height="315" src="https://www.youtube.com/embed/pBlqvnT0sBQ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

ffmpeg の vid.stab プラグインで手振れ補正をしてるだけですが、歩き撮影などでは、まぁまぁ効果ある気がします。

## 2.colabでやったこと

以下の画像の通りです。（Colabを共有するのが抵抗あったので画像とコードで…）

![コメント 2024-05-02 142006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35574/f5fa9ce1-9070-51fd-746e-afc964d69d38.png)

実際にやってる内容（Colabの中身）は以下です。

ffmpeg の vid.stab プラグインが使えるか確認
（enable-libvidstab と表示されればOK）

```sh
!ffmpeg 2>&1 | grep -o enable-libvidstab
```

ファイルのアップロード(元動画）

```python
from google.colab import files
uploaded = files.upload()

for fn in uploaded.keys():
    print('User uploaded file "{name}" with length {length} bytes'.format(
        name=fn, length=len(uploaded[fn])))
```

ffmpgで手ぶれ補正

```sh
!ffmpeg -i $fn -vf vidstabdetect -an -f null - && \ffmpeg -i $fn -vf vidstabtransform -y stb-$fn
```

ファイルのダウンロード(手振れ補正後動画：stb+アップロードファイル名)

```python
from google.colab import files
files.download('stb-'+fn)
```

## 3. 終わりに

私は１分１４秒の動画を試しに手振れ補正してみましたが、「ffmpgで手ぶれ補正」で約４分かかりました。

あまり長い動画でなければColabでもいけるかもしれません。
Colabは無料で使えますし。

ライフハックというほどでもないか :laughing:
アプリパスワードが表示されないときの対処法

メール送信機能を実装させようとしたところ、
Googleの設定を変更し、アプリパスワードを取得しないといけないことがわかりました。

手順
①Googleアカウントにログイン
②セキュリティより２段階認証プロセスを有効に変更
③アプリパスワードを発行

この③の手順にてアプリパスワードを発行するためのボタンが消えていました

![スクリーンショット 2024-05-02 15.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/cbe0f3f1-b148-74e3-ce85-e6fafa9df8f1.png)

ただ、こちらのURLにアクセスするとアプリパスワードの発行ができ、
さらに該当の作成ボタンが出現しました。
どうやらGoogle側はこの機能をあまり使用してほしくないようです。

https://myaccount.google.com/apppasswords

課題のためには必要かと思いますので、ぜひ試してみてください！
OutlookのアドインからREST APIを呼び出したかった

# これはなに？

メール受信をして添付ファイルがあった場合所定のフォルダに保存したい。
graphAPIを呼び出すにはAzure ADで認証(OAuth 2.0)が必要。
認証がなくても、アカウントがログイン済みのOutlookのアドインからなら何とかならないかなあ～と調べた結果の備考録です。

注意：解決していません

# 持ち上げて落とす Outlook REST API

認証なく、アドインの内部からAPIを呼べる！？という文言を見つける。

> アクセス トークンを取得する
Outlook REST API では、Authorization ヘッダーにベアラー トークンが必要です。 通常、アプリは OAuth2 フローを使用してトークンを取得します。 ただし、アドインは、メールボックス要件セット 1.5 で導入された新しい Office.context.mailbox.getCallbackTokenAsync メソッドを使用して、OAuth2 を実装せずにトークンを取得できます。
> isRest オプションを true に設定することにより、REST API と互換性があるトークンを要求できます。

https://learn.microsoft.com/ja-jp/office/dev/add-ins/outlook/use-rest-api

わーい！と思ったら直後に非推奨になる案内があった。絶望。

>  重要
Outlook REST v2.0 とベータ エンドポイントの非推奨
Outlook REST v2.0 およびベータ エンドポイントは 、2024 年 3 月 31 日に完全に非推奨となる予定です。ただし、非公開でリリースされたアドインと AppSource ホスト型アドインは、 2025 年 10 月 14 日に Outlook 2019 の延長サポートが終了するまで REST サービスを使用できます。 これらのアドインからのトラフィックは、除外対象として自動的に識別されます。 この除外は、使用停止日以降に開発された新しいアドインにも適用されます。
アドインは 2025 年まで REST サービスを使用できますが、 Microsoft Graph を使用するようにアドインを移行することを強くお勧めします。 ガイダンスについては、「 Microsoft Graph と Outlook REST API エンドポイントの比較」を参照してください。

## いまMicrosoftのAPIがセキュリティ強化している

https://blogs.microsoft.com/on-the-issues/2023/11/02/secure-future-initiative-sfi-cybersecurity-cyberattacks/

OpenAIから始まったAIの進化により、サイバー攻撃が多くなり、Microsoftも対象になった様子。今後より巧妙になる攻撃に対し、対応すべく、2002年に提言されていたらしいMicrosoft セキュリティ開発ライフサイクル (SDL) の次フェーズに移行するようです。
わー、たくさん変わっちゃう～～～。
ID保護の観点から多要素認証の対応や、新しい管理システムに移行していくようです。このため既知の承認方法や手段が使えなくなっていく・切り替えていく必要があるようです。

## Office アドインの新しい入れ子になったアプリ認証

2024/10にはOffice Outlook アドインからREST APIを使うことができなくなり、アドインの新し入れ子になったアプリ認証を…が普通に入れ子となるということで認証の作業がいらないのかと思ったらそうでもなかった。

> Office アドインの新しい入れ子になったアプリ認証: 2024 年 10 月にレガシ Exchange トークンが既定でオフになる

https://devblogs.microsoft.com/microsoft365dev/new-nested-app-authentication-for-office-add-ins-legacy-exchange-tokens-off-by-default-in-october-2024/

アプリケーションIDが必要ということはAzureサブスクリプション側にいってID登録が必要っぽい。

https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Add-in-SSO-NAA

どうやったってこの手段からは逃れられないみたい…。

https://learn.microsoft.com/ja-jp/office/dev/add-ins/develop/register-sso-add-in-aad-v2

ただ、アドインプラットフォーム登録なので、アドインを複数アカウントに対しての配布であっても、アプリケーションとして登録があれば、APIコールは大丈夫になるのかな…？
jsのnavigationを使ってosとアプリの情報を取得するプログラムを作ってみた

# 初めに
皆さんこんにちは、今回はjsのnavigationを使ってOSの情報を取得するプログラムを作ってみました。
# ファイル構成
今回は多分html一つで大丈夫だと思います
# プログラムを書いていく
早速プログラムを書いていきましょう。
では、htmlに以下のプログラムをコピペしてください。
```html:html

<!DOCTYPE html>
<head>
    <title>navigatorからデータを取得する</title>
    <meta charset="utf-8">
    <style>
   body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    text-align: center;
}

header {
    background-color: #333;
    color: #fff;
    text-align: center;
    padding: 20px 0;
}

.intro, .about {
    padding: 20px;
}

.intro {
    background-color: #f9f9f9;
}

.about {
    background-color: #eee;
}

footer {
    background-color: #333;
    color: #fff;
    text-align: center;
    padding: 10px 0;
}
/* 新しいCSSを追加 */
@keyframes headerAnimation {
    0% { background-color: #333; }
    50% { background-color: #555; }
    100% { background-color: #333; }
}

header {
    color: #fff;
    text-align: center;
    padding: 20px 0;
    animation: headerAnimation 4s infinite;
}
.a {
    color: rgb(109, 109, 255);
}
.a:hover {

    color: rgb(176, 176, 255)

}
    </style>
</head>
<header>
    <h1>navigationから情報を取得する</h1>
</header>
<body>
    <h2>os名:</h2>
    <h2 id="osname"></h2>
    <h2>システム言語:</h2>
    <h2 id="systemlanguage"></h2>
    <h2>UserAgent:</h2>
    <h2 id="useragent"></h2>
    <h2 id>アプリ名:</h2>
    <h2 id="appname"></h2>
    <h2 >appversion:</h2>
    <h2 id="appversion"></h2>
    <h2>cookienabled:</h2>
    <h2 id="cookienabled"></h2>
    <h2>support:</h2>
    <h2 id="vendor"></h2>
</body>
<footer>
    <h2>created by qqn5192</h2>
</footer>
<script>
    let doc = document
let Osname = navigator.platform;
let systemlanguage = navigator.language;
let navuseragent = navigator.userAgent;
let appname = navigator.appName;
let appver = navigator.appVersion;
let cookienabled = navigator.cookieEnabled;
let supported = navigator.vendor;
doc.getElementById("osname").textContent = Osname;
doc.getElementById("systemlanguage").textContent = systemlanguage;
doc.getElementById("useragent").textContent = navuseragent;
doc.getElementById("appname").textContent = appname;
doc.getElementById("appversion").textContent = appver;
doc.getElementById("cookienabled").textContent = cookienabled;
doc.getElementById("vendor").textContent = "supported by"+vendor;
</script>
```
これでプログラムは完成しました。
# 最後に
皆さん、いかがだったでしょうか？今回はjavascriptでosとアプリ情報を読み取るプログラムを作りました。ちなみに今回もheaderのcss部分はchatGPTにやってもらいました。
それではまたお会いしましょう！
CloudFrontのキャッシュ削除を自動化してみる

# 概要

本記事は [AWSでWebアプリを構築してみる](https://qiita.com/ti_and6id/items/9670ee60965a4d10bec7) シリーズの4回目の記事です。
前回の記事は[こちら](https://qiita.com/ti_and6id/items/e9ef9da23b3e33116f6b)。
今回は番外編として、CloudFrontのキャッシュ削除を自動化してみます。

# キャッシュ削除を自動化する理由

開発しているときに、サイトを更新したのにCloudFrontのキャッシュにより内容が反映されるまで時間がかかってしまったり、手動でキャッシュを削除したりすることが手間に感じることがありました。
この問題を解消するためにCloudFrontのキャッシュ削除を自動化し、それにより開発効率の向上を狙います。

# CloudFrontのキャッシュ削除を自動化してみる

## 1. CloudFrontでキャッシュ削除を作成

1. [静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる](https://qiita.com/ti_and6id/items/c257f9d011f84b97ac3e)で作成したCloudFrontのディストリビューションを開き、キャッシュ削除タブから「キャッシュ削除を作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/817b7962-750d-2011-d621-97755679e289.png)


1. オブジェクトパスを追加で「/*」としてすべての領域をキャッシュ削除するように設定する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/ccb25444-e035-97c9-330f-c495fdc5e704.png)

## 2. Lambdaを設定する

1.  マネジメントコンソールからLambdaを開き、「関数の作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/9c83204f-057e-3d1d-b94e-ce54eae391e2.png)

1. 「一から作成」を選択し、関数名に任意の関数名を入力し、ランタイムに「Python 3.X」を選択して、関数を作成する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/1afb288a-056a-c9fc-f271-0bdb4a3380f8.png)

1. 作成した関数で「トリガーの追加」ボタンをクリックし、「ソースの選択」で「S3」を選択し、「Bucket」に[静的ウェブサイトホスティングでホスティングしてみる](https://qiita.com/ti_and6id/items/fe652f89d8919052c91c)で作成したバケットを選択して、「Event Types」で「All object create events」を選択して、トリガーを追加する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/0ad86198-b1f5-27f2-2dde-b6affb4eb87d.png)

1. 作成した関数で設定タブのアクセス権限より、実行ロールのロール名にあるリンクをクリックし、許可タブより「許可を追加」をクリックし、「ポリシーをアタッチ」をクリックし、その他の許可ポリシーで「CloudFront」で検索をかけて、「CloudFrontFullAccess」を選択してポリシーをアタッチする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/f0d212c2-724e-4c98-8a76-8bed2cc0326f.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/0d6f9eb8-6167-dfe3-d267-6679c4f7e39b.png)

1. 作成した関数でコードタブから以下の内容でデプロイする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/d970921f-79bc-687f-937e-105fd633c5df.png)

    ```
    from __future__ import print_function
    
    import boto3
    import time
    
    def lambda_handler(event, context):
        client = boto3.client('cloudfront')
        invalidation = client.create_invalidation(DistributionId='【対象のディストリビューションID】',
            InvalidationBatch={
                'Paths': {
                    'Quantity': 1,
                    'Items': ['/*']
                },
            'CallerReference': str(time.time())
        })
    ```

## 3. キャッシュ削除の自動化の確認

1. [静的ウェブサイトホスティングでホスティングしてみる](https://qiita.com/ti_and6id/items/fe652f89d8919052c91c)で行った手順と同様にバケットのindex.htmlの中身をわずかに変更する

2. ディストリビューションへアクセスし、更新内容が反映されていることを確認する