OmniAICreator/Qiita-1.07M huggingface dataset:
今更ながら、2022年SEOのトレンドは？？？？

皆様こんにちは。玉ちゃんです٩( ᐛ )و

先日、案件において 「SEO」 に関する調査を行わせていただき、折角なのでメモがてらに残させいただきます。

## そもそもSEOって？
### SEO（Search Engine Optimization）

>検索エンジンからサイトに訪れる人を増やすことで、Webサイトの成果を向上させる施策のこと。特定のキーワードで検索された場合の検索結果で、自分のサイトのページを上位に表示させるように、ページやサイト、さらにサイト外の要因を調整することが多い。

Web事業が主流になった現代において聞かぬことはないですし、事業運営の上で必ずしも必要となってくる知識ですよね、、、

もちろん、入社前から僕も聞いたことはあったのですが、詳しく調べるとかなり奥深く、面白い世界だなとわかりました。

### SEO対策には「内部的施策」と「外部的施策」が存在する。

__内部施策について__

内部施策とは具体的に、Webサイト全体のテキストや画像、HTMLタグ、リンクなどサイト内部の要素を改善するSEO対策のことを指します。エンジニアが行う領域の施策ですね。

何故このような対策が必要かと言いますと、ズバリGoogle先生の検索エンジンに正しく情報を伝えるためです。

検索エンジンのロボットというのは、コード内のタグ（見出しタグやタイトルタグ）の内容を元に検索された際の、ヒットワードを選定しています。そのためのあくまで「手助け」を行うために、タグを整理しておく必要があるということです。

僕が案件で、おそらく改善させていただく部分はここでしてmetaタグ内の動的descriptionの設定であったり、画像に対するalt属性の付与、構造データ化等であるとおもいます。

__脱線__

>__よくある議論　h1タグはSEOに影響するのか？？__　
結論としては、h1タグがページ内に複数あろうと無かろうとSEOには影響されない。とされています。Googleのジョン・ミューラー氏（存じ上げません）がおっしゃられているそうですので、流石にその通りなのでは、、、、
> <iframe width='560' height='315' src='https://www.youtube.com/embed/rwpwq8Ynf7s%20' title='YouTube video player' sandbox='allow-scripts allow-same-origin allow-top-navigation-by-user-activation'></iframe> 
>
> ですが、h1が不必要というわけでは無く、見出しタグとして利用されるh1タグというのはユーザビリティの観点から見れば重要とされます。（後程述べますが、ユーザービリティの観点もSEOにおいては重要とされています）titleタグがmetaタグ内に存在しない場合にもh1タグをtitleとして扱われることもあるそうですので全く影響しないというわけでもなさそうです。

**・外部施策について**
外部施策というのは、簡単に言えば広報的な役割を多くなすものです。記事を読んでいるとよく目にする「被リンク」の取得であったり、自社のWebサイトに対して言及してもらう「サイテーション」、あとはSNSによる自社のWebサイト宣伝などが大きく挙げられます。

被リンクを増やすのはGoogleがコンテンツ評価を行う上でも最重要視される

***EAT***

***・Expertise（専門性）***

***・Authoritativeness（権威性）***

***・Trustworthiness（信頼性）***

にも大きく影響されるとされSEO対策に直接影響のある重要な外部的施策項目とされています。

## Googleの検索アルゴリズムアップデートの影響

直近でいうと2021年6月16日にGoogleは**The Page Experience Update**と呼ばれる検索アルゴリズムのアップデートを行いました。

このアップデートによって、Googleのページランキングを決定する要素として『ユーザに対する良質なエクスペリエンス』を提供しているページを探すようになりました。

これが、意味することは**単に内部的、外部的SEO対策が満たされているのみでは検索エンジンにおいて上位に表示されるとは限らない**ということです、、（ﾅﾝｼﾞｬﾄ）

そしてこのアップデートによって定義された新しい基準というのは、**Google Core Web Vitals**と呼ばれ、Webサイトの**応答性、表示速度、デザイン性**などが測定されています。

## ズバリ2022のトレンドは「**個別最適 < 全体最適**」

先ほど紹介したEATのは変わらず重要視されるため、今まで意識されていた個別のページに対する内部的施策ももちろん重要視されますが、近年では結果として**Webサイトそのものの価値が評価されやすくなっています。**

「ビッグキーワード」が類似するWebサイト同士を比べると、EAT、Google Core Web Vitalsを元に優劣が顕著に出てしまいそうです。

すなわち、  **「トレンドに沿ったビックキーワード」＋「ユーザービリティ」＋「細々した施策」** 

**の総合力で評価されるのが現代のSEOです。**

結論だけ見ると、細々した内部施策がSEOに大きく影響しないように思えてきますが、数年前と比べWebサイトの量が膨大に増えてきている、そして増え続けていく今後において仕方なくも思えますね。

とは言っても、**SEOは総合力の結果指標として捉える**とするならば、チリツモじゃないですが内部施策について向き合っておく必要があると思います。
yarn startを実行するとerror:0308010Cエラーが発生

<h1>概要</h1>
yarn startでサーバーが立ち上がらない(Error: error:0308010C:digital envelope routines::unsupported)

<h2>理由</h2>
Nodeのバージョンが高すぎるのが原因らしい。v14.18.1以下まで下げる必要がある。
推奨版をダウンロードしたんだけどなあ。

<h2>解決策</h2>
versionを下げよう！以下参考に。先人の知恵に感謝。

https://qiita.com/k3ntar0/items/322e668468716641aa5c


<h2>困ったら</h2>
まずは公式ドキュメント。これは定石だね。

https://yarnpkg.com/getting-started/install
サクラエディタで空行削除と改行をタブにする操作を自動化する方法

## 目的
システムの内容をExcelに記入する為、サクラエディタで
ひたすら「空欄を削除する置換」と「改行をTABにする置換」の
操作を実施していて面倒になり、マクロの記録機能で操作を自動化しました。

下記の2つの作業をマクロに記録しました。
・空欄を削除する置換
・改行をTABにする置換

## マクロ登録方法
1．置換したい内容をサクラエディタに張り付ける

2．[ツール] → [キーマクロの記録開始(R)]の順にクリックする
![1キーマクロの開始.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/46412ee2-4f7b-c855-481c-5b0ae5244d66.png)


3．[検索(S)] → [置換(R)]の順にクリックして置換の画面を表示させる
※空行を削除する置換
![2．検索から置換.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/f00c0d94-c178-9d23-738f-2065b3373ae3.png)

4．置換の画面で下記のように置換前、置換後を入力し「すべて置換(A)」をクリックする
置換前(N)：^[\r\n]+
置換後(P)：
※\は¥マークです。
※空行を削除したいので置換後に何も入れない
![4から行消すすべて置換.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/5666f948-fb51-ba59-ecb7-8c99b51f884a.png)


5．「OK」をクリックする
![5か所を置換しましたok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/0a303e38-2f87-730d-3922-63a3bf7b1048.png)


6．[検索(S)] → [置換(R)]の順にクリックして置換の画面を表示させる
※改行をタブに変換する置換
![6検索から置換.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/9ffdaa23-086d-6532-8d2c-9f7d8745e54b.png)


7．置換の画面で下記のように置換前、置換後を入力し「すべて置換(A)」をクリックする
    置換前(N)：\r\n
    置換後(P)：\t
※\は¥マークです。
![8すべて置換.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/281eb9bd-35f6-222a-463e-abab7763166a.png)


8．「OK」をクリックする
![9ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/27235126-4095-702c-7adb-1eacfaeba63c.png)


9．[ツール] → [キーマクロの記録終了＆保存（M）]
![10ツールキーマクロの記録終了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/79662a15-7129-33b4-200c-b4abcec714de.png)


10．任意のマクロ名を入力し、任意の場所にマクロを保存する
![10マクロの終了保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/76ec9d6f-e434-0618-1ef7-4719ba6dba50.png)



## マクロ実行方法

1．修正したい内容をサクラエディタに張り付ける
![修正したい内容.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/80e7656e-b138-fe02-0305-539116bb1077.png)


2．[ツール] →　[キーマクロの読み込み(A)]の順にクリックする
![1キーマクロの読み込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/fa7efcf4-f2b2-d279-52ea-4f778958ea24.png)

3．保存したマクロ名を選択する
![保存したマクロを指定する.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/bc0db48f-fbbf-4133-f33f-0328ee8d41ac.png)


4．[ツール]→[キーマクロの実行(D)]の順にクリックする
もしくはキーボードのキーを
Shift + Ctlr + L を同時に押す
![2キーマクロ実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/973bd382-9921-a388-9247-e503f3dbb2a9.png)

5．記録した空行削除と改行をタブに変更する操作が実行される
![スクリーンショット 2022-11-08 135103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/794b6a59-43aa-89fd-9c21-fa5ec9234164.png)



サクラエディタを閉じるまでは
Shift + Ctlr + L を同時に押すと記録した操作が実行できます。
Salesforce認定platformアプリケーションビルダー試験勉強徹底解説

こんにちは

今回は
Salesforce認定platformアプリケーションビルダー試験の勉強方法を解説します

今回の内容は動画でも公開しています

https://www.youtube.com/watch?v=7LrOLZiZA1w

<iframe width="560" height="315" src="https://www.youtube.com/embed/7LrOLZiZA1w" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## Salesforce認定platformアプリケーションビルダー試験　とは？

まず立ち位置としてはSalesforce認定platformアプリケーションビルダー試験の資格の位置づけです


詳細はこちらをご確認ください


https://tandc.salesforce.com/credentials

![ｐぁｔ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/bc8def4e-fb28-88fb-05d8-3367b719bf1e.png)


認定platformアプリケーションビルダーは「開発者やアーキテクトのファーストステップ」というものです


## Salesforce認定platformアプリケーションビルダー試験詳細を確認しよう



受験ガイドには試験詳細がございます
ぜひご確認してください

https://sfdc.co/EG_PlatformAppBuilder_JA

 Salesforce 認定 Platform アプリケーションビルダー試験の詳細は次のとおりです。 

* 内容: 多肢選択/複数選択方式の 60 問 
* 試験の所要時間: 105 分 
* 合格点: 63% 
* 受験料: 20,000 円（税抜） 


## Salesforce認定platformアプリケーションビルダー試験　推奨教材


この試験に対応する自己学習教材はとして以下を推奨しています（英語コンテンツを含む）： 

* Trailmix: 【Salesforce 公式】認定 Platform アプリケーションビルダー資格対策 (https://trailhead.salesforce.com/ja/users/welcome4/trailmixes/prepare-for-your-salesforce-platform-app-builder)
* Superbadge: Security Specialist (https://trailhead.salesforce.com/en/content/learn/superbadges/superbadge_security)
* Superbadge: Process Automation Specialist (https://trailhead.salesforce.com/ja/content/learn/superbadges/superbadge_process_automation)
* Superbadge: App Customization Specialist (https://trailhead.salesforce.com/ja/content/learn/superbadges/superbadge_lightning_platform_app_builder)


## Salesforce認定platformアプリケーションビルダー試験　　練習問題

Platform アプリケーションビルダー試験に向けた学習　のTrailheadには公式練習問題として何度も解けるフラッシュカードがございます。
ぜひ解いてみてください

また、解説動画を作成していますのでよければご活用ください

https://www.youtube.com/playlist?list=PLz8HSF-SrLeFbxLWqQHK0XZdn662RG6jo
【Unity】自作ボタンの関数をonclickに設定する方法

ヒエラルキー> buttun> onclickにbuttunドロップ
ButtunScript>Replay(自作関数)

###
```
    public void ReplayGame()
    {
         SceneManager.LoadScene("MainScene");

    }

```

注意
publicにすること
void スタート、アップデート× → 自作関数にすること。
PhotoShop2023 ver.24 でグリッドのショートカットキー　command+@ が効かない

＜ケース＞
PhotoShop2023 ver.24 でグリッドのショートカットキー　command+@ が効かない
パソコンはMacBookAir Ventura13.0

＜対処＞
グリッドのショートカットキーを別に作成することで解決した

＜手順＞
PhotoShopメニュー　編集＞キーボードショートカット
ダイアログが表示されるので項目の[表示]を展開
[グリッド]のショートカットキー部分をクリック
カーソルが立っている状態で　commandキー押しながら任意のキーを押す

この例ではアンダーバーを採用できていますが、すでに利用している場合はその説明が表示されます。
![スクリーンショット 2022-11-08 12.30.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516464/1787f0bd-16fb-93a2-5af1-dfb1e0b748f9.png)

command+_ でグリッドが表示されました。
![スクリーンショット 2022-11-08 12.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516464/2630aa48-eed2-dffe-448b-0bc043982ff2.png)
Elixirで気軽にpersistent_termを使う

たまたまあるソースコードを読んでいたら[persistent_term]という面白そうなErlangモジュールに出くわしました。

https://www.erlang.org/doc/man/persistent_term.html

## persistent_termとは

- [OTP] 21.2から導入された
- [Erlang Term Storage (ETS)][ets]と同様に高速で値を取得できるインメモリKey-Valueストレージ
- ETSと異なり読み込みに特化して最適化されており、その代償として書き込みは遅い
- [BEAM]バーチャルマシンに対して1インスタンス存在し、どのモジュールからもアクセスできる
- 衝突を防ぐため、モジュール名もしくはモジュール名と何か他の[Erlang Term][term]と組み合わせた[タプル][tuple]をキーをすることが推奨されている
  - 例、`MyModule`
  - 例、`{MyModule, :secret_code}`

詳しくは[Erlangの公式ドキュメント][persistent_term]をご覧ください。


ETSについては以前軽くまとめたものがあるので参考になれば幸いです。

https://qiita.com/mnishiguchi/items/54846209c37d74157868

## 論よりRUN

### IExシェルを起動

```bash
iex
```

### `persistent_term`の中身を見てみる

```elixir
iex> :persistent_term.get()
...long list...

iex> :persistent_term.get() |> length()
22
```

なんと、まだ何もしていないのにネットワーク関係やロガー関係の設定が保存されているようです。

ですので、それらの値を誤って消さないように、やっぱりキーの名前空間に注意が必要ですね。

### 適当なキーでアクセスしてみる

```elixir
iex> :persistent_term.get(:foo)
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: no persistent term stored with this key

    :persistent_term.get(:foo)
    iex:3: (file)
```

キーが存在しない場合はエラーになるようです。

### 値を挿入してみる


```elixir
iex> :persistent_term.put({MyApp, "feeling"}, "good")
:ok

iex> :persistent_term.put({MyApp, "language"}, "Japanese")
:ok
```

簡単ですね。

### 値を取得してみる


```elixir
iex> :persistent_term.get({MyApp, "feeling"})
"good"

iex> :persistent_term.get({MyApp, "language"})
"Japanese"
```

これも楽勝。

## 何に使えるのか
- 一度書き込まれたら読み込みしかされない設定関係に使えそう

## 事例研究: elixir-toniq/mentat

キャッシュに使えるElixirパッケージは複数存在していますが、その一つである[elixir-toniq/mentat]に[persistent_term]が利用されていました。

やはりSupervisorのinitコールバックで一度だけ書き込みをしてあとは読み込むだけという使い方をしています。

https://github.com/elixir-toniq/mentat/blob/7f1811779ca2dfc80dcb30fe5d70d5809afb3abb/lib/mentat.ex#L262

https://github.com/elixir-toniq/mentat/blob/7f1811779ca2dfc80dcb30fe5d70d5809afb3abb/lib/mentat.ex#L281-L287

[ets]: https://www.erlang.org/doc/man/ets.html
[persistent_term]: https://www.erlang.org/doc/man/persistent_term.html
[elixir-toniq/mentat]: https://github.com/elixir-toniq/mentat
[term]: https://www.erlang.org/doc/reference_manual/data_types.html
[tuple]: https://hexdocs.pm/elixir/Tuple.html
[BEAM]: https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine)
[OTP]: https://en.wikipedia.org/wiki/Open_Telecom_Platform

じゃ、また。

## ご参考までに

https://qiita.com/piacerex/items/e0b6e46b1325bb931122

https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf
Personal Access Tokenをコミットせずに、Github PackagesをPrivateに使う方法

# 前提
私は普段はmacOSでNodeのパッケージ管理にyarn@berryを使ってますのでyarnベースで解説します。

Github Packagesにプライベートで公開する方法は記述しません。公開された後にそれを利用するベストプラクティスの話です。

Organazationやuser名はご自身の環境に読み替えてください。

# [方法1] `.npmrc`もしくは`.yarnrc.yml`をコミットの対象外にする
PrivateなGithub Packagesに公開したパッケージを他のプロジェクトからインストールするには、

npmなら`.npmrc`、yarnをお使いなら`.yarnrc.yml`にご自身の[Personal Access Token(=PAT)](https://github.com/settings/tokens)(権限は`read:packages`のみでOK)を記述します。

```yml:yarnrc.yml
yarnPath: .yarn/releases/yarn-3.2.1.cjs
nodeLinker: node-modules

npmScopes:
  'suyama-daichi':
    npmAlwaysAuth: true
    npmRegistryServer: 'https://npm.pkg.github.com/'
    npmPublishRegistry: 'https://npm.pkg.github.com/'
    npmAuthToken: ghp_************************************

```

<details>
<summary>npmの場合</summary>

```
//npm.pkg.github.com/:_authToken=ghp_************************************
@suyama-daichi:registry=https://npm.pkg.github.com/
```

</details>

これらのファイルを `.gitignore`に追加するなどしてコミット対象から除外すれば、自身のトークンがコミットされることはありません。

# [方法2]環境変数を参照する
簡単な構成なら方法1でもいいのですが、`.npmrc`や`yarnrc.yml`に記述される設定はレジストリの認証情報だけではないので、ファイルごとコミット対象外にするのは得策ではないです。

それでは、PATをVSCodeで実行されるターミナルの環境変数に含めてしまい、それを構成ファイルから参照ましょう。

VSCodeの `settings.json`で設定できます。

https://qiita.com/y-w/items/614843b259c04bb91495

```json:settings.json
{
  // …
  "terminal.integrated.env.osx": {
    "GITHUB_PACKAGE_TOKEN": "ghp_************************************"
  }
  // …
}

```

<details>
<summary>Windowsの場合</summary>

```json:settings.json
{
  // …
  "terminal.integrated.env.linux": {
    "GITHUB_PACKAGE_TOKEN": "ghp_************************************"
  }
  // …
}

```

</details>


> プロジェクトごとに設定するなら`settings.json`ではなく`.code-workspace`を使えます。

`.npmrc`と`yarnrc.yml`は環境変数を参照できます。

https://yarnpkg.com/configuration/yarnrc

https://npm.github.io/installation-setup-docs/customizing/the-npmrc-file.html

```yml:yarnrc.yml
yarnPath: .yarn/releases/yarn-3.2.4.cjs
nodeLinker: node-modules

npmScopes:
  'suyama-daichi':
    npmAlwaysAuth: true
    npmRegistryServer: 'https://npm.pkg.github.com/'
    npmPublishRegistry: 'https://npm.pkg.github.com/'
    npmAuthToken: ${GITHUB_PACKAGE_TOKEN}

```

<details>
<summary>npmの場合</summary>

```
//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGE_TOKEN}
@suyama-daichi:registry=https://npm.pkg.github.com/

```

</details>


`setting.json`の設定を反映させるために、ターミナルを再起動します(VSCodeでもOK)

### インストール
これで、プライベートパッケージをインストールできます。

```bash
yarn add -D @suyama-daichi/sample-types
```

<details>
<summary>npmの場合</summary>
```
npm install -D @suyama-daichi/sample-types
```

</details>
パソコン甲子園2022 個人レポート

# パソコン甲子園とは
今年で20周年となる。  
会津大学が主催する高校生・高専生のためのICT分野の全国大会。  
今年は競技プログラミング部門とモバイル部門、CG部門がありました。  
公式は[こちら](https://pckoshien.u-aizu.ac.jp/)
  
今年は久しぶりの現地開催となり、企業として参加してきたので、その時の様子をレポートします。

# プログラミング部門 (1日目)
二人一組で問題を解いていきます。  
当日は36チームの参加でしたが、これは本戦であり、予選には全国から533チームも参加していたとのことです。  

学生が課題に取り組んでいる中、私も同じ問題をもらって、一緒に解いていました。  
今年含め過去問は[こちら](https://pckoshien.u-aizu.ac.jp/programming/)
私は3問目以降戦意喪失し、冊子をそっとじしました。  

実施中は何もすることがないと思っていましたが、実況を聞いているのが面白かったです。  
「予選で1位、2位を取っていたチームが、他チームが数問回答を提出し正解を出しているのに対して、まだ1問も提出していません。」  
「これは苦戦しているのではなく **『潜伏』** という戦略を取っていると考えられます。」  
「後ろの方にあるけど意外と簡単という情報を他チームに知られることを防ぐことができる。最後まで見返しができる。というメリットがあります」
私(すげぇ)

実際の様子はこちらです。  
[パソコン甲子園2022 プログラミング部門競技実況](https://www.youtube.com/watch?v=P0JWHmV0sNE)

## 関和休題
1日目の終わりには学生同士の交流会がありました。  
そこにも顔を出し、様子を見ていました。  
積極的に声をかけている子がいるな～と何人かを目で追っていましたが、その子たちはプログラミング部門及びモバイル部門で優秀な成績を納めていました。  
コミュ力大切だなぁと思いました。(小並感)

# モバイル部門 (2日目)
与えられたテーマに沿ったサービスを制作、プレゼンします。  
![DSC_0147.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595099/1a25519a-65b7-f00e-2287-228fec86447a.jpeg)

今年のテーマは「温故知新」とのことです。
実際のプレゼンの様子はこちら。  
[パソコン甲子園2022 モバイル部門競技](https://www.youtube.com/watch?v=tmhLiQvS4M4)

学生でインフラの構築とモバイルアプリを作成をできてしまうなんて、爪の垢を煎じて呑んでもいいと思いました。

## 気になったチーム箇条書
* **JK制服の流行サイクルの分析提案**
* **Twitterトレンドが今後トレンドが上昇するか下降するかをシミュレーション**
  どちらの製品も統計学的な視点で、今後の流れを予想するサービスとなっています。  
  前者は、過去の流行から実際に今年の流行を割り出した実績があり、後者はUIもおしゃれで、企業賞を受賞しています。
* **タスク自動管理アプリ**  
  グランプリを取ることになるこのアプリ。論文をもとに最適なスケジュールを組んでくれる。また、200人以上の学生に実際に使ってもらい、アンケート結果も反映したオンリーワンのサービスとなっています。  
  デザインやコーディング能力もさることながら、人に周知し使わせるという、簡単には身に着けられない能力を持ったチームだと感じました。
* **画像検索アプリ**
  写真で撮影したものが何かを、AIモデルを使用して判定し、そのものに付随する情報を閲覧できるアプリ。  
  話を聞いたところ、自分たちで画像を用意し学習させ、20種類の物を判定できるモデルを作ったと聞きました。高校生も機械学習を回せる時代なんですね。  
  私「AWSのGPU環境使ったの？」  
  学生「GoogleCloud使いました」  
  私「なぜそんな渋い環境をw」  
  学生「300$分のクレジットもらったからですw」  

## 結果
灘高が競技プログラミング部門及び、モバイル部門二冠を達成。
「去年はプログラミングの問題が1問解けず2位となりましたが、今年は全問正解で優勝できて嬉しいです」とコメントしており、胸熱でした。
また、驚いたことに、モバイルアプリは3人で3か月で完成させたとのことです。  
学生の自分に限らず、社会人の今でも同じことができるとは思えません...

# まとめ
学生にも直接話を聞くことができ、大変楽しかったです。  
いろいろ持ち帰る物はありましたが、物理的な物として、現地で飲んだ[名倉山](https://nagurayama.jp/)というお酒がおいしかったので、買って帰りましたとさ。
Pythonにおける備忘録

## 概要
pythonにおける小技を自分用にまとめておく

## 目次
- 空のデータフレーム作成
- np.whereを用いた条件を満たす行列要素の抽出
- リストの中から重み（確率）付けしてランダムに抽出

## 空のデータフレーム作成
空のデータフレームを作成し，リストを格納した．
```
df = pd.DataFrame()
a = [0, 1, 2] 
df['a'] = a #リスト格納
print(df)

>>>    a
    0  0
    1  1
    2  2
```
Jupyter Notebookで実装している場合，以下によってDataFrameを全て表示することが可能である．
```
pd.set_option('display.max_rows', None) #indexに相当
pd.set_option('display.max_columns', None)
```

## numpyのスライスの注意点
範囲外の位置を指定してもエラーにならない。
開始位置が範囲外の場合は空リストになり、終了位置が範囲外の場合は開始位置以降の全要素が返る。


```
array_3d = np.random.randint(2, size=(3, 3, 3))
for x0 in range(3):
    for y0 in range(3):
        for z0 in range(3):
            AN = np.sum(array_3d[x0-1:x0+2, y0-1:y0+2, z0-1:z0+2] > 0)
            neighbour_values = array_3d[x0-1:x0+2, y0-1:y0+2, z0-1:z0+2].flatten()
            print(x0, y0, z0, AN, neighbour_values)

>>> 0 0 0 0 []
    0 0 1 0 []
    0 0 2 0 []
    0 1 0 0 []
    0 1 1 0 []
    0 1 2 0 []
    0 2 0 0 []
    0 2 1 0 []
    0 2 2 0 []
    1 0 0 0 []
    1 0 1 0 []
    1 0 2 0 []
    1 1 0 0 []
    1 1 1 14 [1 0 1 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 0]
    1 1 2 9 [0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0]
    1 2 0 0 []
    1 2 1 8 [0 0 1 0 0 1 1 0 1 1 1 0 0 1 0 1 0 0]
    1 2 2 5 [0 1 0 1 0 1 1 0 1 0 0 0]
    2 0 0 0 []
    2 0 1 0 []
    2 0 2 0 []
    2 1 0 0 []
    2 1 1 10 [0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 0]
    2 1 2 6 [1 1 0 1 1 0 0 1 1 0 0 0]
    2 2 0 0 []
    2 2 1 6 [1 0 1 1 1 0 0 1 0 1 0 0]
    2 2 2 3 [0 1 1 0 1 0 0 0]
```


## np.whereを用いた条件を満たす行列要素の抽出

```
a = np.random.randint(10, size = (3,4,5))
b = np.where(a==5)
print(a)
print(b)

>>> [[[9 5 1 4 6]
      [1 9 1 3 3]
      [0 7 4 9 4]
      [1 8 5 0 8]]

     [[2 3 8 3 5]
      [8 9 4 0 4]
      [4 1 2 9 3]
      [8 9 7 6 3]]

     [[0 1 7 8 0]
      [3 8 2 8 8]
      [4 1 7 7 5]
      [6 5 7 7 5]]]
     (array([0, 0, 1, 2, 2, 2]), array([0, 3, 0, 2, 3, 3]), array([1, 2, 4, 4, 1, 4]))
```

データ型はタプルであることが下記の通りわかる．

```
print(type(b))
print(b[0])

>>> <class 'tuple'>
    [0 0 1 2 2 2]
```

この場合，zip関数を用いることで条件を満たす各軸の要素を抽出可能である．

```
for x0, y0, z0 in zip(b[0], b[1], b[2]):
    print(x0, y0, z0)

>>> 0 0 1
    0 3 2
    1 0 4
    2 2 4
    2 3 1
    2 3 4
```

## リストの中から重み（確率）付けしてランダムに抽出
random.choices()で，リストから重み（確率）付けしてランダムに要素を取得できる．取得してくる要素数を指定可能で，重み（確率）を指定できる．その重み（確率）の総和は0にさえならなければ特にエラーにはならない．
また，リストで返されるため注意が必要である．
```
list1 = [1, 3, 5, 7, 9]
list2 = [0.2, 0.3, 2, 3, 1]

a = random.choices(list1, weights=list2, k=1)
print(a)
print(a[0])

>>> [5]
　　　5
```
LaravelにsanctumでAPI認証を入れる

LaravelでBladeを使いながら開発していましたが、そろそろフロントをVue.jsなどに変えた上でバックエンドを切り離そうと思ってます。

REST API接続に変えることになるのですが気になるのがセキュリティ。
ブラウザ上でログインしたユーザのみがAPIを使えるようにする必要があります。

# LaravelのAPI認証認可ライブラリ（Sanctum）のインストール
LaravelではSnctumとPassportという二つのライブラリが選択肢としてあるようです。
公式マニュアルを見る限りではSanctumの方が推奨されていたので、早速Sanctumをインストール。

以下を参考にさせてもらいました。

https://codelikes.com/use-laravel-sanctum/

Laravelのauthライブラリをベースに画面でログインされるとsanctumライブラリで利用できるトークンが発行され、api.php内で指定しておけば、sanctumの認可処理が都度走るという仕組みのようです。

# Postmanでのテストをどうするか
ここで課題になるのがPostmanを使うときにどうするか。

Postmanは結構便利で他システムで活用していました。
今回もPostmanでAPI開発時のデバッグを行ったり、APIのテストなどを行いたいのですがsanctumの認証認可とうまく連携できるのだろうか。。。

こちらも調べてみたら方法がありました。

https://wonwon-eater.com/laravel-sanctum-postman/#outline__3

少々設定が複雑ですがスムーズに動くようになりました。
paiza.ioでelixir その49

# 概要
paiza.ioでelixirやってみた。
Task使ってみた。

# サンプルコード

```
1..100
|> Stream.take(10)
|> Task.async_stream(fn i ->
	Process.sleep(10)
	IO.puts(to_string(i))
end)
|> Enum.to_list()
|> IO.inspect

task = Stream.interval(100) 
|> Task.async_stream(&(&1))
|> Enum.take(5)
Enum.map(task, &(IO.inspect(&1)))

task = Task.async(fn -> 
	1 + 1 
end)
Task.await(task)
|> IO.inspect

tasks = [Task.async(fn -> 
	1 + 1 
end), Task.async(fn -> 
	2 + 3 
end)]
Task.await_many(tasks)
|> IO.inspect

tasks =
	for i <- 1..10 do
		Task.async(fn ->
			Process.sleep(i * 5)
			i
		end)
	end
tasks_with_results = Task.yield_many(tasks, 1000)
results =
	Enum.map(tasks_with_results, fn {task, res} ->
		res || Task.shutdown(task, :brutal_kill)
	end)
for {:ok, value} <- results do
	IO.inspect(value)
end

```

# 実行結果

```
1
2
3
4
5
6
7
8
9
10
[
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok,
  ok: :ok
]
{:ok, 0}
{:ok, 1}
{:ok, 2}
{:ok, 3}
{:ok, 4}
2
[2, 5]
1
2
3
4
5
6
7
8
9
10
```

# 成果物

https://paiza.io/projects/1m9iMXK_iQ0N1s-KJS91cA


以上。
DNNに必要な画像データの水増し

# DNNで使える画像データ水増し手法
## はじめに
DNN(Deep Neural Network)を活用したディープラーニングにおいて、画像学習をさせようとしたときの話。
DNNでクラス分類の精度を上げるには、より良いデータを取得する必要があります。
良いデータとは主に、
- 画像枚数が十分
- 各タグの画像枚数が等しい
- 正確なアノテーション

などとされています。
これらを実現するにあたって必要なものは一貫して「画像データの枚数」にあります。
そこで、今回は「ガンマ変換」と「平滑化」を用いて、画像の水増しをする手法を備忘録的に書いておきます。

また、実際のサンプルデータとコードは[github](https://github.com/wassy310/DNN_Image-data-padding-method)に置いてあります。

## ガンマ変換(ガンマ補正)
輝度値を変化させることで実装できる変換手法です。
これにより、画像を明るくしたり暗くしたりして水増しします。
サンプルコードの
```
gamma = 0.4
```
の実数部を変えることで、輝度を変えることが可能です。
閾値は1で、数字が小さいと暗く、大きいと明るくなります。
0.4～1.6の範囲で、0.1刻みで水増ししていくのがおすすめです。

### ガンマ補正とは
ガンマ補正の処理は、次の式で表せます。
```math
y = x^γ
```
また、グラフは以下のようになります。
![gamma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1472510/03f3cddf-9d02-e90f-234b-1969deb154fb.png)

理論的には、「画素値がn倍になると、出力の明るさもn倍になる」という比例の関係にあります。(リニア)
しかし、実際の出力では上記のグラフのように、理論結果と同じ結果になるとは限りません。
そこで、ガンマ補正という手法を使い、実際の出力をリニアに近づける処理を行います。


## 平滑化
平滑化という難しそうな言葉を使っていますが、言ってしまえば「ぼかし処理」です。
OpenCVを使った平滑化の手法にはいくつか種類がありますが、今回は **cv2.blur()** を使用しました。
こちらもガンマ変換と同様に、
```
blur_size = (30, 30)
```
の実数部を変えることで、どのくらいぼかすかを指定することができます。
数字が大きくなるとよりぼやけます。
おすすめは(5, 5)～(20, 20)です。

### 平滑化処理の内容
平滑化処理でどのようなことが行われているかをテストしてみました。
コードもこちらに載せておきます。(githubのレポジトリには入れていません)
```
import cv2

blur_size = (5, 5)
img = cv2.imread('./images/sample.jpg', cv2.IMREAD_COLOR)

file = open('./testText/sample01.txt','w')
for i in range(10):
    for j in range(10):
        file.write(str(img[i, j, 0]) + ' ')
    file.write('\n')
file.close()

img = cv2.blur(img,blur_size)
file = open('./testText/sample02.txt','w')
for i in range(10):
    for j in range(10):
        file.write(str(img[i, j, 0]) + ' ')
    file.write('\n')
file.close()
```
※ (5, 5)ピクセルで平滑化処理をした場合のコードです。
サンプル画像の左上10 × 10ピクセル分のB値(RGBのB値)を、処理前と処理後でtxtファイルに出力しています。

処理前後のtxtファイルはこのようになりました。
<p>
<img width="300" alt="処理前" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1472510/9c5e0529-0b26-8469-36fe-95a948d97837.png">
<img width="310" alt="処理後" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1472510/9fd21dee-6bed-0259-b2d0-2b693c09ca4c.png">
</p>

5~10で並べられたB値が、6と7だけでソートされています。
平滑化処理は「カーネルの範囲内にある画素の平均値を取って」処理していることがわかりました。

## おわりに
「おすすめ」としてどのくらいの範囲で指定すると良いよ～ってのを書きましたが、用途にもよると思うので、自分でサンプル画像などを使って試してみると良いと思います。
Swift JSON+CodableでURL変換できない文字列をOptionalにする

# 環境
Xcode 14.1

# 概要

以前も[似たような記事](https://qiita.com/hyuga_amazia/items/7d2f7f4ae48ec37c1292)を書いていますが、JSONのレスポンスを解析するとき、`Codable`が使われますが、このときCodable対応したstructにURL型が含まれていて、それに対応するJSONのパラメータが`URL(string:)` で結果がnilになる文字列(空文字、日本語、スペースetc)の場合、DecodingErrorとなってしまいます。

エラーにならない対応とするため、URLとして変換できないものはOptionalにしたいと思います。
以前のコードでは別クラスを作っての対応を行なっていましたが、別クラスを使わずに対応できる方法を紹介します。

## エラーになるCodable


```swift
let json = """
{
  "id": 1234,
  "name": "Hello World!",
  "url": ""
}
""".data(using: .utf8)

struct MyData: Codable {
    let id: Int
    let name: String
    let url: URL?
}

let ret = try! JSONDecoder().decode(MyData.self, from: json!) // DecodingError
```

上記のコードは、URL?型としてurlを変換したいのですが、JSONのデータのurlはURLとして生成できない空文字のため、たとえOptionalにしてもDecodingErrorが発生してしまいます。

# 対応
`init(from decoder: Decoder)`を実装して、エラーに対応します。

```swift
struct MyData: Codable {
    let id: Int
    let name: String
    let url: URL?
    
    init(from decoder: Decoder) throws {
        let container: KeyedDecodingContainer<MyData.CodingKeys> = try decoder.container(keyedBy: MyData.CodingKeys.self)
        
        self.id = try container.decode(Int.self, forKey: MyData.CodingKeys.id)
        self.name = try container.decode(String.self, forKey: MyData.CodingKeys.name)
        self.url = URL(string: try container.decode(String.self, forKey: MyData.CodingKeys.url)) // ←一度Stringに変換した後、URLを生成
    }
}
```

注目するのはURLの生成部分で、一度Stringクラスを生成した後、自分のパラメータにURLとして与える、という手順を`init(from decoder: Decoder)`で行うことでDecodingErrorを回避できます。

## Codableコードの自動生成
このコードはいちいち書くのは手間だと思いますので、`Add Explicit Codable Implementation`で自動生成して、URL部分だけ書き換えたりするのがいいと思います。
⌘キーを押しながらstructクリックでメニューが出ます。

![スクリーンショット 2022-11-08 10.50.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/e9b237cb-e1ce-a4d2-8919-30e946928a65.png)

以下、自動生成するとこんな感じになります。

```swift
struct MyData: Codable {
    let id: Int
    let name: String
    let url: URL?
    
    enum CodingKeys: CodingKey {
        case id
        case name
        case url
    }
    
    init(from decoder: Decoder) throws {
        let container: KeyedDecodingContainer<MyData.CodingKeys> = try decoder.container(keyedBy: MyData.CodingKeys.self)
        
        self.id = try container.decode(Int.self, forKey: MyData.CodingKeys.id)
        self.name = try container.decode(String.self, forKey: MyData.CodingKeys.name)
        self.url = try container.decodeIfPresent(URL.self, forKey: MyData.CodingKeys.url)
        
    }
    
    func encode(to encoder: Encoder) throws {
        var container: KeyedEncodingContainer<MyData.CodingKeys> = encoder.container(keyedBy: MyData.CodingKeys.self)
        
        try container.encode(self.id, forKey: MyData.CodingKeys.id)
        try container.encode(self.name, forKey: MyData.CodingKeys.name)
        try container.encodeIfPresent(self.url, forKey: MyData.CodingKeys.url)
    }
}

```
Raspberry PIにgethをインストールする方法

Raspberry PIにgethをインストールする方法の備忘録です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399135/e1e79845-2703-ece9-89c4-70436826c649.png)

以下サイトからの引用です。
:paperclip: https://snapcraft.io/install/geth/raspbian
アクティブストレージを利用して複数枚の画像を投稿した際の単体テスト

アクティブストレージを利用して複数枚の画像投稿には成功した。
しかしテストコードで詰まったので記録。
結論
```ruby
RSpec.describe Item, type: :model do
  before do
    @item = FactoryBot.build(:item)
    @item.images = [ fixture_file_upload("/files/test_image.jpg")]
  end
```
このように書き換える。
画像１枚のときは fixture_file_uploadだけでよかったのですが、複数枚になったことで配列で渡す必要があったのですね。
AWSを勉強していたらDGADomainRequest.Bの検知に引っかかった話

# はじめに
ZOZOには[福利厚生](https://corp.zozo.com/recruit/welfare/)の一環としてクラウドトレーニング費用補助制度があります。この制度を利用することで、毎月100ドルまでAWSのサービスを利用できます。今回は、その制度を活用してAWSの勉強をしていたところ、GuardDutyのDGADomainRequest.Bに引っかかった時の話をまとめます。

# 検知内容
GuardDutyによって以下が検知されました。

```
Trojan:EC2/DGADomainRequest.B
 
EC2 instance i-02ac327aa638d30d1 is querying algorithmically generated domains. Such domains are commonly used by malware and could be an indication of a compromised EC2 instance.
```

[DGADomainRequest.B](https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_finding-types-ec2.html#trojan-ec2-dgadomainrequestb)は、ドメイン生成アルゴリズム (DGA) で生成された思われるドメインにアクセスしようとしているのを検知する仕組みだそうです。

# 前提
- 対象のEC2インスタンスはDBアクセス用の踏み台サーバです。したがって、外部ドメインへのアクセスをすることは意図的なものではありません。
- EC2インスタンスにSSHログインするには秘密鍵が必要です。
- EC2インスタンスのセキュリティグループは22番ポートでIP制限はしていませんでした。
- 制度利用者ごとにAWSアカウントが個別に用意されており、当然ながらZOZOTOWNなどのサービスへの影響はありません。

# 被害状況の確認
鍵認証が突破され、EC2インスタンスに不正ログインされていないかを最初に確認しました。これを最初に実施した理由は、EC2インスタンスが乗っ取られていた場合の被害が大きいからです。

まず、SSH成功回数を確認します。

```
# grep -c Accepted /var/log/secure
1
```

こちらの実行結果により、SSH成功は一回であることがわかりました。この成功は自分の操作によるものだと断定しました。理由は、自分が一度だけSSHしたという記憶に合致するのと、ログに含まれる送信元IPアドレスが自分のものであると確認できたからです。

次に、SSH失敗回数を確認します。

```
# grep -c invalid /var/log/secure
1187
```

こちらの実行結果により、SSHブルートフォース攻撃により、SSHが失敗しまくっていることがわかりました。

とりあえず、鍵認証が突破されていないことがわかり、一安心です。

# 原因
SSHでは、「SSHサーバが接続元IPアドレスを逆引きしてホスト名を取得し、そのホスト名を名前解決して接続元IPアドレスと同じものが得られるか」といった確認処理を行う場合があるそうです。（AWSのテクニカルサポートで教えていただきました）
この処理が実行されるかは設定次第です。今回使用したAMI（ami-0c3fd0f5d33134a76）では、EC2インスタンス内の `/etc/ssh/sshd_config` で以下のように該当の動作に関する設定がコメントアウトされています。デフォルトは"yes"なので、逆引きが行われることになります。これにより、対象のドメインにアクセスしようとして検知された可能性が高いと考えました。

```
#UseDNS yes
```

なお、試しに「GuardDutyにより検知したドメイン名」と「sshdログから確認したIPアドレス」を使って、正引きと逆引きを試してみましたが、成功しませんでした。おそらく、既にドメインの登録が既に削除されてしまったと考えられます。

まとめると、「DGAで生成されたことが疑われるドメインに紐づくIPからSSHされ、送信元IPアドレスの逆引き名前解決をEC2インスタンスが行ったことにより、GuardDutyに検知された」と推察されます。

# 今回のケースでの対策
`UseDNS no` に設定する方法も考えられますが、そもそもSSHでIP制限していない状況を改善したいと考えました。
今回のEC2インスタンスの用途として、 `EC2 Instance Connect` ができれば十分です。その場合、例えばregionがap-northeast-1であれば、許可する送信元IPアドレスを `3.112.23.0/29` のみに絞ることができます。ただし、このIPは変動しうるので注意が必要です。以下が対象のIPレンジです。
https://ip-ranges.amazonaws.com/ip-ranges.json
トレイルヘッドが翻訳されて表示される

[UI関係のトラブルに戻る](https://qiita.com/Keiji_otsubo/items/cc344223cfa02db6bed7)


+ [Trailhead に翻訳を依頼しなくても、コンテンツの一部が英語で一部がスペイン語で表示され続ける](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgWK3)

:::note
Restarting my laptop did the trick and resolved my issue.
:::
【Vim】忘れがちな個人的便利コマンドまとめ

## キー移動

* 前の単語の末尾に移動する
`ge`

* 指定した行に移動
`:10`

* 空白以外をまとめて移動
`H`
`J`
`K`
`L`

* 選択中の行をクリアしてInsertModeに入る
`cc`

* 選択中の単語をクリアしてInsertModeに入る
`cw`

* カーソル以降を削除してInsertModeに入る
`C`

* 行頭に移動し、InsertModeに入る
`I`

* 行末に移動し、InsertModeに入る
`A`

* リドゥできる
`ctrl + r`

* カーソルが画面に端に来るように移動
`zs`
`ze`

* 左右に半画面移動
`zL`
`zH`

* 画面中央に移動
`:gm`

* 単語の定義をファイル内で検索し移動
`gD`

## ファイル操作

* 編集にファイルを移動する
`:n`
`:p`

* 編集中のファイルを保存する
`:wn`
`:wp`

* 現在のバッファを確認
`:ls`

* バッファのファイルを開く
`:b1`

* バッファを閉じる
`:bd1`

* ファイルツリーを開く
`:Ex`

* 右にファイルツリーを開く
`Vex`

* 上にファイルツリーを開く
`Sex`

* 左にファイルツリーを開く
`Lex`

* ファイルツリーで削除
`D`

* ファイルツリーでリネーム
`R`

## コマンド操作

* レジスタを指定して単語をヤンク
`ayw`

* レジスタを指定して単語をペースト
`ap`

* レジスタの内容を確認
`:reg a`

* vimを開いている最中にshellコマンドを実行
`:! curl`

* 文字列置換のフラグ(:s/置換対象/置換後の文字/フラグ)
`g グローバル, c 確認, e Noエラー, i 大文字区別なし, l 大文字区別あり`

* 文字列の検索
`:vim[grep] plugin ./vim.md`

* コマンドのヘルプを確認できる
`:help cc`

## ウインドウ操作

* 現在以外のウインドウを閉じる
`ctrl + wo`

* 現在のウインドウを閉じる
`ctrl + wq`

* 全てのウインドウを閉じる
`:wqa`

* ウインドウの高さを変更
`:resize +10`

* ウインドウの幅を変更
`:vertival resize +10`

## タブ操作

* 新しいタブを開く
`:tabnew ./vim.md`

* タブを移動
`gt`
`gT`

## ウインドウ操作

* ウインドウを移動
`ctrl w + HJKL`

## 検索

* 単語単体を検索
`/\<vim\>`

* ファイルから検索
`:vimgrep 検索文字列 **/*.py`

## Plugin

### vim-unimpaired
前後の移動操作を楽にするプラグイン

* バッファの切替
`[b`
`]b`

* vimgrepの検索結果の切替
`[q`
`]q`
リスケール変換(Rescale)

[Teradata Vantage - Vantage Analytics Library](https://docs.teradata.com/r/Vantage-Analytics-Library-User-Guide/January-2022)[2022/9/22時点]の翻訳です。
(リリース番号 : 2.1.1 | リリース日 : January 2022)
> この記事はVantageアナリティクスライブラリ シリーズのコンテンツです。

# 概要
リスケール変換を使用すると、データの最大値と最小値に基づく線形リスケーリング関数を使用して、連続した数値列のデータの上限と下限を制限することができます。リスケーリングは、ある範囲内のデータを必要とする、あるいはよりよく機能するアルゴリズムで有用です。

カラムの値を指定した下限値/上限値でスケールします。
[1,2,3]を0～1でスケールすると[0,0.5,1]になります。

# 前提条件
・Teradata Vantageインスタンスにアクセスできること。
・Vantage アナリティクス・ライブラリがインストールされていること。

::: note info
Vantage アナリティクス・ライブラリのインストールについて、既にVantageを導入頂いているお客様はTeradataサポートサービスにお問い合わせください。
Vantage Express (評価版)やクラウドサービスのDIYでご利用頂く場合は[Teradata Dounload](https://downloads.teradata.com/download)からダウンロードし利用可能です。
Vantage アナリティクス・ライブラリのインストール手順は「[Vantageアナリティクス・ライブラリのインストール](https://qiita.com/ykswi/items/12d0da2ac69b4b161881#vantage%E3%82%A2%E3%83%8A%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AF%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)」の記事に従い行います。
:::

# データの準備
## サンプルデータの入手とデータベースへの格納方法
こちらの「[チュートリアル用のサンプルデータを用意する](https://qiita.com/tmsky/items/4d86ca35aef753290020)」を参照ください。


# 実行方法
## SQLから実行する場合の例
lowerbound/最小値、upperbound/最大値を指定する。
```SQL
CALL td_analyze (
  'vartran',                          /* 分析手法　*/
  '
  database        = QID;              /* データベース名 */
  tablename       = Superstore;       /* テーブル名 */
  rescale =
     {rescalebounds (lowerbound/0, upperbound/1), columns (sales)}
     {rescalebounds (lowerbound/0),               columns (sales/sales2)}
     {rescalebounds (upperbound/1),               columns (sales/sales3)}
  ;                                   /* 導出項目の定義 */
  '
);
```

:::note information
出力結果をテーブルに書き込む場合は以下オプションを指定可能です。
outputdatabase = 出力データベース名;
outputtablename = 出力テーブル名; 
overwrite = {true | false}; --- 未指定の場合はtrueで上書きします
:::

## 出力結果
データ量が多いため上位10件を表示しています。
|Sales|sales2|sales3|
|:-|:-|:-|
|0|0|-22637.036|
|0.000004947425651235824|0.11200000000000004|-22636.924|
|0.000017315989779325377|0.39199999999999996|-22636.644|
|0.000018022764872359068|0.408|-22636.628|
|0.000019082927511909604|0.432|-22636.604|
|0.000020054743264830926|0.454|-22636.582|
|0.000023853659389887002|0.54|-22636.496|
|0.000024118700049774634|0.546|-22636.489999999998|
|0.00002650406598876334|0.6000000000000001|-22636.435999999998|
|0.00002809430994808914|0.6360000000000001|-22636.399999999998|
|～|～|～|

# おわりに
:::note information
サンプルコードはSQL関数から掲載し順次Pythonコードも掲載していく予定です。
:::

:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
Pythonでndjsonファイルを扱う方法

# はじめに

最近ndjson形式のファイルを扱うことが増えてきたため、今回はPythonでndjson形式のファイルを扱う方法を簡潔にまとめてみた。
ndjsonというモジュールがあるらしいので、それを使用してみる。

# 参考記事など

https://pypi.org/project/ndjson/

https://dk521123.hatenablog.com/entry/2022/08/30/224248

# テスト用ndjsonファイル準備

以下のような値をもつファイルを作成し、test_input.ndjsonとして保存した。


```
{"username":"Mac","hobby":["baseball","soccer","tennis"]}
{"username":"John","hobby":["baseball","cooking"]}
{"username":"Miki","hobby":["cooking","reading"]}
{"username":"Andy","hobby":["baseball","soccer"]}
```

# モジュールのインストール

以下のコマンドでndjsonモジュールがインストールできる。


```
pip install ndjson
```

# ndjsonモジュールの使用方法

## ndjsonファイルの読み込み

ndjsonファイルの読み込みは以下のように書くことができる。

```python
import ndjson

with open('test_input.ndjson', encoding='UTF-8') as f:
    input_data = ndjson.load(f)
    print(input_data)
    print(type(input_data))
```

読み込み結果は以下のようになる。このように ***ndjson.load()*** を使用するとjsonをリスト形式で取得できる。

```
[
 {'username': 'Mac', 'hobby': ['baseball', 'soccer', 'tennis']}, 
 {'username': 'John', 'hobby': ['baseball', 'cooking']}, 
 {'username': 'Miki', 'hobby': ['cooking', 'reading']}, 
 {'username': 'Andy', 'hobby': ['baseball', 'soccer']}
]
<class 'list'>
```

また、 ***ndjson.dumps()*** を使用するとテキストへ変換することができる。

```python
import ndjson

with open('test_input.ndjson', encoding='UTF-8') as f:
    input_data = ndjson.load(f)
    text_data = ndjson.dumps(input_data)
    print(text_data)
    print(type(text_data))
```

結果は以下のようになる。どうやらテキストは改行されて表示される(改行コードが入っている)らしい。

```
{"username": "Mac", "hobby": ["baseball", "soccer", "tennis"]}
{"username": "John", "hobby": ["baseball", "cooking"]}
{"username": "Miki", "hobby": ["cooking", "reading"]}
{"username": "Andy", "hobby": ["baseball", "soccer"]}
<class 'str'>
```

## ndjsonファイルへの書き込み

ndjsonファイルへの書き込みは、以下のように ***ndjson.dumps()*** を使用する。
なお、 ***ndjson.dump()*** を使用する際は、引数にリスト型オブジェクトを入れる必要があるので、テキストなどは ***ndjson.loads()*** で型を変更する必要がある。


```python
import ndjson

with open('test_input.ndjson', encoding='UTF-8') as f:
    input_data = ndjson.load(f)
    text_data = ndjson.dumps(input_data)
    converted_data = ndjson.loads(text_data)

with open('test_json_output.ndjson', 'w', encoding='UTF-8') as f:
    ndjson.dump(converted_data, f)
```


ちなみに、テキストをハードコードする場合は、以下のように改行コードを入れてあげればよい。

```python
import ndjson

text = '{"username": "Mac", "hobby": ["baseball", "soccer", "tennis"]}\n{"username": "John", "hobby": ["baseball", "cooking"]}'
    converted_data = ndjson.loads(text)
    
with open('test_json_output.ndjson', 'w', encoding='UTF-8') as f:
    ndjson.dump(converted_data, f)
```

# まとめ
今回は、Pythonでndjson簡単に扱うことができるようになるndjsonモジュールについて簡潔にまとめてみた。jsonモジュールと同じような感じで簡単に利用できるので、ぜひ試してみてほしい。
複数列の最大値/最小値を求める(SPSS Modeler データ加工逆引き3-19)

## 複数列の最大値/最小値を求める

![スクリーンショット 2022-11-03 18.10.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6f99fcfd-38b4-9dae-49b5-305c93904ac7.png)

## 1.想定される利用目的

・ 顧客行動予測のための特徴量作成
・ 設備故障や異常検知のための特徴量作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/max_n.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-11-03 18.11.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/74aeb86b-8238-629e-cf43-d2c5c56b9cc2.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-11-03 18.12.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bba63f42-0163-f7f6-8d9e-2260a7eaaf92.png)

b.[フィールド作成]ノードを編集します。
![スクリーンショット 2022-11-03 18.12.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0c98b11a-5a1d-a2a7-9162-d26b28475bff.png)

式ビルダーを利用すると便利に入力できます。[max_n(リスト)]でリストから最大値を選びます。@&#xFFF0;FIELD_BETWEEN関数でリストを作成しています。
![スクリーンショット 2022-11-03 18.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/54c1d646-13ad-ae67-00e0-77eea893622b.png)

c.[フィールド作成]ノードを編集します。リストの作り方に@&#xFFF0;FIELD_MATCHINGを利用しました。
![スクリーンショット 2022-11-03 18.14.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d42205ea-ec42-e00a-82da-01b4378af3bb.png)

[プレビュー]します。完成しました。
![スクリーンショット 2022-11-03 18.14.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/58837156-807c-4ecd-5b38-3ecf4e2bdcf0.png)


#### 注意点

複数列の合計を求める時はsum_nを利用します。

https://qiita.com/416nishimaki/items/27c322f7da4967d4caf3

## 4.参考情報

#### @&#xFFF0;FIELD_BETWEENが扱われている記事

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-16/

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-15/

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
FirebaseFirestoreSwiftを利用したデコード

導入して便利だったので自分の備忘録としてメモ

FirebaseFirestoreSwiftを利用しなければ、Firestoreのコレクションのフィールドを抜き出す必要があった。活用すれば、`queryDocumentSnapshot.data(as: TaskModel.self)`で一発でデコードできる

Before: `let data = queryDocumentSnapshot.data()`、`let label = data["label"] as? String ?? ""`
After: `queryDocumentSnapshot.data(as: TaskModel.self)`

```swift:TaskModel.swift
struct TaskModel: Codable {
  @DocumentID var id: String?
  var label: String
  var userId: String
  var createdAt: Date

  enum CodingKeys: String, CodingKey {
    case id
    case label
    case userId
    case createdAt
  }
}
```

```swift:CloudFirestoreService.swift
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift

final class CloudFirestore {
    static let shared: CloudFirestoreService = .init()
    private init() {}

    private var db = Firestore.firestore()

    func getCollection(userId: String?, completion: @escaping ([TaskModel]) -> Void) {
        db.collection("tasks").whereField("userId", isEqualTo: userId).getDocuments { (snapshot, error) in
        guard let documents = snapshot?.documents else {
          print("Not Found Documents")
          return
        }
                
        let tasks = documents.compactMap { (queryDocumentSnapshot) -> TaskModel? in
            return try? queryDocumentSnapshot.data(as: TaskModel.self)
        }
        completion(tasks)
     }
   }
}
```

## 参考URL
[公式の方法でFirestoreでCodable #firebase #firestore #codable - Qiita](https://qiita.com/fromkk/items/33357fc6aa90e1098b48)
[Mapping Firestore documents using Swift Codable - Youtube](https://youtu.be/3-yQeAf3bLE)
Oracle Analytics Cloud：キャンバスを自動更新してみる

# はじめに
Oracle Analytics Cloud（**OAC**）では、キャンバスに様々なビジュアライゼーションを配置することができます。
「データのリフレッシュ」アイコンをクリックするだけで、キャンバスのすべてのビジュアライゼーションを更新（再検索）することが可能です。
「データのリフレッシュ」を自動的かつ定期的に実行する方法を紹介します。

# 準備したワークブック
このようなワークブックを準備しました。
自動更新を試したいだけなので、今回はワークブックの中身は問いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/3bd19e09-4d4d-cd9f-13e4-1cb66f9ffd6b.png)

編集モードに移ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/c900f772-df57-2b4b-da57-948761333531.png)

# キャンバスのプロパティを変更
キャンバスのプロパティを表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/91fb536a-58bd-e6d4-10da-f8bd67b63665.png)
「データの自動リフレッシュ」を「有効」に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/d787fc79-51f0-09ce-a31e-ac5574d84b50.png)
リフレッシュ間隔を指定して、「OK」をクリックして閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/f6b2ac4e-faaf-924f-1887-6d088a74d939.png)
ワークブックを保存します。

# 自動リフレッシュ
保存したワークブックを開きます。
「データのリフレッシュ」アイコンが、このアイコンになっている場合は自動リフレッシュを開始するための待機中ですので、クリックしていみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/b19f4c3f-f7f9-6c87-5195-5f3b706a4ff1.png)
アイコンがこのように変化します。指定した時間が来るまで待機しているときのアイコンです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/1dc41799-785b-efd3-a9e4-9164ab71fbb1.png)
指定した時間がやってくると、このアイコンに変化してデータが更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/148ad634-a5d4-e66e-6977-8c783c984705.png)

# おわりに
この機能を使用すれば、手動でリフレッシュしなくても画面を開いておくだけで自動的にデータがリフレッシュされます。
繰り返し検索することになりますので、無用なトラブルを避けるためあまりに短い間隔を設定するのは避けたほうが良いかも知れません。
実情にあわせて設定してみてください。
gitメモ

gitコマンドについての自分用メモ。順次更新していく予定。1月24日更新。2月3日更新

新規にリモートリポジトリを作る場合
-
①githubのホームでNewをクリックし、リポジトリを作成。
②変更履歴を管理したいフォルダに移動し、以下のコマンドを実行。
③コマンドを入力（このコマンドはgithubでリポジトリ作成後に遷移するページに書いてある）
```
echo "# リポジトリ名" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.ユーザー名/リポジトリ名.git
git push -u origin main
```

git init
-
現在いるディレクトリがgitで管理されるようになる。
ls -a で隠しファイル.gitがあるか確認。
.gitがあるということはgitで管理されているファイルであるということ。

git status
-
ファイルが状態（ステージング）を確認。

git add [option] ファイル名
-
ファイルの変更をステージングする
-A:変更ファイル全てをステージングする

git commit [option]
-
ステージングされている変更をリポジトリに反映させる。
-m: git commit -m "second-commit"
のようにコミット時のコメントを一気に入力できる。

git push origin main
-
ローカルにコミットしたものをリモートにプッシュする。大元を変更することになるので要注意。

git log
-

git reset [commitの番号頭5桁くらい]
-
変更履歴を過去に遡る。番号はgit logで確認する。

git branch
-
現在いるブランチを確認できる

git branch [名前]
-
名前ブランチを作成できる

git branch -d [ブランチ名]
-
指定したブランチを削除

git checkout [ブランチ名]
-
ブランチをブランチ名に切り替える

git log --all --decorate --graph
-
現在いるブランチやメインブランチのルートを視覚化できる

git merge [ブランチ名]
-
統合には向き(どのブランチにもう一方のブランチを統合するのか？)があるので注意。
統合元が今いるブランチで、統合したいブランチをブランチ名に書く。つまり、指定したブランチがHEADの指しているブランチ（今いるブランチ）に取り込まれる。
git statusでコンクリフトが発生しているか確認できる。

git clone [リモートリポジトリのSSH]
-
リモートリポジトリのファイルを手元にコピーする
他人のリモートリポジトリの内容を新規に取得する場合に利用

git push origin ローカルのブランチ名:リモートのブランチ名
-
ローカルで作ったブランチをリモートに反映させる。

git pull origin [:]
-

git remote -v
-
利用中のローカルリポジトリのリモートリポジトリがどこにあるか表示させる。
originの場所がわかる。

.gitignoreファイルについて
-
touch .gitignoreでギット管理しているファイル内に隠しファイルを作成する。
パスワードなどgitに保存したくないファイルやディレクトリーを指定する。
パスを指定して無視する対象を決める。
「echo 'パス' >> .gitignore」でファイルに書き込む。
無視している対象を確認するには
「git status --ignored」コマンド。

https://www-creators.com/archives/1662

git reflog
-
logのHEAD@{番号}を確認できる

git reset
-
ステージングを元に戻す

git reset コミットID
⇨コミットIDのところまでコミットを戻す

git reset --soft HEAD@{番号} （または、コミットID）
⇨ファイルの変更内容はそのままで、そのコミットまで戻る

git reset --hard HEAD@{番号} （または、コミットID）
⇨ファイルの変更等はリセットし、そのコミットまで戻る

https://codelikes.com/git-reset/#toc5

https://tech-blog.rakus.co.jp/entry/20210528/git#revert%E3%81%A7%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99
MacのOSアップデート時の「xcrun: error」の対処方法

macOS Venturaにアップデートした際に発生したエラーの対処方法

# エラー内容
```
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

# 対処方法

## command line tools for xcodeをインストールする
```
xcode-select --install
```

# さいごに
macOSのアップデートは毎回ひやひやします。。
Azure Fundamentals(AZ-900)：Azure の基礎: Azureの管理とガバナンスについて説明する「Azureと対話するためのツール」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「Azureと対話するためのツール」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azureの管理とガバナンスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/describe-azure-management-governance/)
◇対応するモジュール
[Azure と対話するためのツールについて説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-features-tools-manage-deploy-azure-resources/2-describe-interacting-azure)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azureの管理とガバナンスについて説明する「Service Trust Portal」](https://qiita.com/fsd-jume/items/9794137391d96190b27d)

## Azureと対話するためのツール
### Azure Portal
**GUIでサブスクリプションを管理できるWebベースのコンソール**
・簡単なWebアプリから複雑なクラウド開発まで、すべてのものを構築/管理/監視可能
・カスタムダッシュボードでリソースを整理して表示可能
・端末を問わずポータルにアクセス可能
・すべてのAzureデータセンターに構成されており、
　-回復性と継続的な可用性を実現
　-近くのデータセンターを使用することでネットワークの速度低下も回避可能
・継続的に更新されるが、メンテナンスによるダウンタイムは発生しない

### Azure Cloud Shell
**ブラウザからCLIでAzureリソースを作成/構築/管理可能なツール**
・ローカル環境のインストールや構成は必要とせず作業可能
・Azure Portalから使用可能
・Azureの資格情報を基に安全に自動的に認証
・ShellはAzure PowerShellとAzure CLI(Bash)から選択して使用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/354b01ca-c474-dea5-4888-0f853f489cd1.png)

## 次の学習内容
**◆Azure Arc**

https://qiita.com/fsd-jume/items/d66dc8213fad4b448de1

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
【Swift】Codableを使用してJSONをSwiftのオブジェクトに変換する方法

Swift の <font color="#A276E4">**Codable**</font> プロトコルは、JSON を Swift のネイティブな構造体やクラスに簡単に変換します。JSON と同じキーと値を保持するデータ型を設計し、<font color="#A276E4">**JSONDecoder**</font> を使用して変換するだけです。

:::note warn
重要： この記事を投稿したのが2019年07月08日（月）で自身の法人サイトの方でしたけれども、公式サイトの更新などでブログ系のメンテナンスが大変だったので、ここに過去の投稿の移動とこれからの記事を投稿をする予定です。
:::

次は、私たちが良く扱うJSONの例です。

```swift
let jsonString = [
    {
        "name": "武田信玄",
        "age": 26
    },
    {
        "name": "上杉謙信",
        "age": 25
    }
]

let jsonData = Data(jsonString.utf8)
```

これは2人の人間を配列に格納するもので、それぞれ名前と年齢を持つ。

そして、これらのフィールドを保持する事の出来るSwiftの構造体を作る必要があります。<font color="#A276E4">**Codable**</font> が持つ唯一の要件は、構造体の中のすべてのプロパティが <font color="#A276E4">**Codable**</font> に準拠していることです - 私たちの場合、それは文字列と整数です。

この構造体を追加する事から始めます。

```swift
struct Person: Codable {
    var name: String
    var age: Int
}
```

あとは、JSONデータをその`Person`構造体の配列に決定していきます。これは <font color="#C93E3F">**throw**</font> 操作なので、<font color="#C93E3F">**try**</font> を使う必要があります。以下、コード例です。

```swift
let decoder = JSONDecoder()

do {
    let people = try decoder.decode([Person].self, from: jsonData)
    print(people)
} catch {
    print(error.localizedDescription)
}
```

その結果、JSONから2つの`person`構造体を保存することになります。そして、Swiftの型にパースされているので、型安全な方法でそれらを参照することができます。

## オプション
APIのレスポンスで帰ってきた構造体が異なるキー名を利用している時、これをSwift側の`Person`構造体に合わせることが出来ます。例えば、`"user_name"`と`"user_age"`がレスポンス側のキー名として、これを`name`と`age`に置き換えたい時は下記のように行います。

```swift
struct Person: Codable {
  var name: String
  var age: Int

  enum CodingKeys: String, CodingKey {
    case name = "user_name"
    case age = "user_age"
  }
}
```

以上となります。
ESP32で基板開発するときに参照すべきドキュメント

# 目的
ESP32は非常に優れたデバイスで、ユーザーも多いので多くの情報をウェブ上で見つけることができるが、ハードウェア関連の情報は結構離散的で探すのに苦労する。今回ESP32を使った基板開発を行ったので、参照したドキュメントなどをまとめて残してみる。

## [ESP32-S3 データシート](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf)
各デバイス（S3, C3など）のデータシートが存在する。各ピンの特殊機能などが詳しく書かれている。デバイスによっては入力専用ピンなどが存在するので、基板作り終わったあとにビックリしないように一度は見たほうが良い。

## [ESP32-S3-WROOM データシート](https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf)
ESP32-S3-WROOMは外付けのクロックやフラッシュメモリなどがパッケージ化されているタイプのことで、ESP32-S3はその中のマイコン単体を指す。パッケージ化された状態の使い方が書いてある。フラッシュやPSRAMがどれだけ載っているかは結構忘れるので、データシートを見てちょくちょく思い出す必要あり。

## [ESP32-S3 ハードウェアデザインマニュアル](https://www.espressif.com/sites/default/files/documentation/esp32-s3_hardware_design_guidelines_en.pdf)
基板を作るときにESP32をどのように配置・配線すればよいかが記載されている。特にアンテナにまつわる基板上での配置に制約があり、注意する必要がある。配置によっては電波感度が下がってしまうらしい。アンテナ一体型タイプは使いやすいが、アプリケーションによってはアンテナ外付けを選択するのもありかと思う。

## [ESP32-S3 Devボード設計情報](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html)
Devボードは基板を作る上でかなり参考になる。プログラム書き込み周りとかはじっくり見たほうがよい。

## [KiCADで基板設計](https://www.kicad.xyz/)
KiCADを使う上で重要なことが網羅されている素晴らしいサイト。KiCADを使っていて何か行き詰まったらここをのぞいてみていただきたい。

## [ESP32-S3 KiCADシンボル](https://github.com/espressif/kicad-libraries)
KiCADのフットプリント・シンボルライブラリがなかなか見つからなかったが、本丸のEspressif社がGithubに載せていた。これは安心して使えると思う。

## [KiCADでテストPADを作る](https://www.pcbway.com/blog/PCB_Design_Tutorial/KiCad___________Pcbnew____________________via_______1.html)
チェックピンを設置することなく、手軽にテストパッドを設けることができる（この手法はかなりすごいと思う）。部品もいらず、CAD上の定義だけでよい。ESP32に限った話ではないが、KiCADを使うならこの手法は取り入れるべき。

## その他基板設計上重要なポイント
- Strapping PINという起動時に使うピン（S3の場合GPIO0, 45, 46, 3）がある。これらのピンを使ったときの副作用がよくわからない（最悪起動しないこともありえる）ので、使わないのが無難。ESP32-S3-WROOMのデータシートに記載されている。
- ESP32-S3-WROOMにSPIフラッシュが載っていて、SPIのピンが外にでている（S3の場合GPIO35, 36, 37）。SPIポートとして使えるらしいが、これらも通常用途では使わないのが無難。
- ノーマルESP32-WROOMでは、GPIO12がプルアップされているとSPIフラッシュが1.8Vモードになりプログラム書き込みができなくなるらしい。ESP32-S3のデータシートを見る限り、そのような記載を見つけられなかったが、結局確証を得られなかったので使用しないことにした。。。

# 所感
設計中に見ていた情報は全部載せたと思うので、自分用のリファレンスとして残しました。基板はコストがかかり、設計期間が長く、製造も長く、手戻りも長く、それでいて失敗するとすごく怒られるという理不尽さがあるので、ちゃんとした情報をベースに設計したいところ。でも、基板できあがってもみんなしらーっとしてんだよなぁ。「これは奇跡の産物なんですよ」と伝えたい。。。