OmniAICreator/Qiita-1.07M huggingface dataset:
2023年スタイルズ Advent Calendarまとめ

2023度のスタイルズ Advent Calendarを閉めたいと思います。

結果は以下の通りでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/19e60389-aa5e-d18a-1f62-b5638b8560b3.png)

# 1. 2023年スタイルズアドベントカレンダー

今年も、忙しいメンバーが多く苦戦いたしました。
しかし、参加者は4名でした。残念！

どういうネタが多かったか分析してみました。

## 1. Nextcloud系の記事

Nextcloud系の記事が10本あります。

Nextcloud Hub 6でAIを動かす！ #nextcloud - Qiita
https://qiita.com/ynott/items/e7bdee68b0592f9c6823

外部ストレージ（S3）にストレージクラスが指定できるようになりました | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/files_external_s3_storageclass.html

「Nextcloudハンドブック 基本と構成」と「Nextcloudハンドブック 機能」の2本を公開しました！ | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/nextcloud-handbook.html

Nextcloudの全文検索機能と検索テクニック | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/nextcloud-fulltextsearch-search_tips.html

プッシュ通知の制限メッセージが追加されました | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/push_notification_limit_messages.html

WebDAVアップロードで、ファイルの更新日時がアップロード日時に変更される | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/webdav_modified_date.html

Nextcloud Hub 6: 健全な会議文化と初のローカル AI アシスタント | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/nextcloud-hub-6-healthy-meeting-culture-and-the-first-local-ai-assistant.html

英語ヘルプドキュメントの変更(代替案)と非表示化 | Nextcloud日本公式サイト
https://nextcloud.stylez.co.jp/blog/techblog/changed_help_document.html

Nextcloud Hub 7 プレスリリース
https://nextcloud.stylez.co.jp/wp-content/uploads/2023/12/EN-2023-12-12-Press-release-Nextcloud_ja.pdf

スタイルズで取り扱っているNextcloudはオープンソースなので情報も多めですね。

## 2. コンテナ系の記事

コンテナの利用の記事が2つありました。

ShellフォームとExecフォームの違いとENTRYPOINTとCMDの使い分けについて #dockerfile - Qiita
https://qiita.com/ynott/items/ad2e6f608051bc60fec6

自己証明書を利用しているHarborにイメージをプッシュする #kubernetes - Qiita
https://qiita.com/s_oshima/items/1ece9e1d5e007a9bc7b7

TLS/SSL証明書を使わないといけないけど、自己証明書しかとれないという時にはまるポイントについて解説は助かりますね。

Jetsonの為にx86_64でARM用イメージをマルチアーキテクチャビルド #GitHubActions - Qiita
https://qiita.com/ynott/items/c4739e8693c27958f0b0

## 3. AI系の記事

AIの記事が3つありました。
スタイルズでもOpenAIの生成AIを使って業務に活用にしていますが、ドンドン身近になりますね。

Thunderbirdでも生成AIしたい Aifyのご紹介 #thunderbird - Qiita
https://qiita.com/ynott/items/2a3c724150a9b5761ce1

LlamaIndexとStreamlitでChatbotを作成してみる #ChatGPT - Qiita
https://qiita.com/tkg-70/items/ad415550c9a810772d5b

Nextcloud Hub 6でAIを動かす！ #nextcloud - Qiita
https://qiita.com/ynott/items/e7bdee68b0592f9c6823

## 4. HW系の記事

モゲマイクロ対策をマグネット接続方式のMicroUSBケーブルで #自作キーボード - Qiita
https://qiita.com/ynott/items/19672862c6707e99838f

自作キーボードでやっちゃうPro Microの話は、非常に切実な問題です。

## 5. AWS系の記事

AWS認定 SAA-C03の再認定を受験してきた #AWS - Qiita
https://qiita.com/S_Katz/items/0c238d8c7fe03601453b

再認定の話はあまり聞いたことがないので為になりますね。

# 2. まとめ

今年は残念ながら、アドベントカレンダー完走ならず！
来年もよろしくお願いいたします｡
terraform-docsインストールでハマったこと

# はじめに
業務でterraform-docsを使用する機会があり、ツール導入から行ったのですが、詰まったところがあったので、共有します。

# terraform-docsとは
terraformモジュールからドキュメントを生成するツールです。
どんなリソースブロックを使用しているのか、変数に指定しているものはどんなものがあるのかなどをdocs化してくれるツールです。

# ざっくり手順
## **Chocolateyインストール**
terraform-docsはmacの場合、Homebrewでインストールでき、Windowsの場合、ScoopかChocolateyでインストールできます。今回はChocolateyでインストールするので、まずChocolateyの導入から。

通常は以下のコマンドでインストールできるのですが、セキュリティソフトで弾かれることがあります。(今回詰まったのはここでした…)
~~~md
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
~~~
そこで今回はオフラインインストールをします。

https://docs.chocolatey.org/en-us/choco/setup
 
1. ChocolateyのサイトからChocolateyのパッケージをダウンロード(https://chocolatey.org/api/v2/package/chocolatey/)
1. ダウンロードしたnupkgをzip解凍ソフトで解凍
1. 解凍した `chocolatey.0.XX.XX\tools`にてコマンドプロンプト実行(管理者権限)
1. 以下のコマンドを実行
~~~md
@powershell -NoProfile -ExecutionPolicy Bypass -Command  .\chocolateyInstall.ps1
~~~

※プロンプトの応答後、chocoと入力し、インストールしたバージョンが表示されたら完了
~~~md
C:\ProgramData\chocolatey\bin>choco
Chocolatey v2.2.2
Please run 'choco -?' or 'choco <command> -?' for help menu.
~~~

## **terraformインストール**
以下のコマンドを実行
~~~md
choco install terraform-docs
~~~

プロンプトの応答後、terraform-docs -vと入力し、インストールしたバージョンが表示されたら完了

# おわりに
以下の記事を参考にインストール実施しましたが、terraform-docsインストールまで記事になっているものがなかったので、まとめさせて頂きました。

# 参考

https://qiita.com/m-tmatma/items/0ea55b972a010806af8b
機械学習の原理を学ぶ上でつまづきやすい数学上の留意点まとめ

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>

# 機械学習の原理を学ぶ上でつまづきやすい数学上の留意点まとめ

覚書であり正確さを保証するものではありません。各項目で概要と出典を記載しています。およそ見知らぬ数学の大半は[EMANの物理学](https://eman-physics.net/)様と[高校数学の美しい物語](https://manabitimes.jp/math)様で解決します。

書きかけの項目は随時更新いたします。

## 線形代数
大規模計算やらベクトル計算やらに応用される。定義から順序良くたどると行列もろもろの見通しが格段にいいと思っているため細かめに記載。

[EMANの物理学 > 物理数学 > 線形代数とは何か](https://eman-physics.net/math/linear01.html)

### 集合
「何かを集めたもの」はすべて集合である。線形代数はもちろんのこと、確率・統計においても集合の理解が非常に重要となる。

集合に属するひとつひとつの要素を「元」と呼ぶ。
また、ある集合 $A$ に属する元だけで集合 $B$ を構成したとき、$B$ を $A$ の部分集合と呼ぶ。
$$ B \subset A $$

[「集合」出典: フリー百科事典『ウィキペディア（Wikipedia）』](https://ja.wikipedia.org/wiki/%E9%9B%86%E5%90%88)

#### 補足：開区間、閉区間
ある区間の数を元とする集合があるとき、端っこの数字を含むか含まないかを閉区間および開区間を使って表現する。

- 開区間とは、「$a$ より大きく $b$ より小さい数全体の集合」のこと
 $$(a,b)$$
- 閉区間とは，「$a$ 以上 $b$ 以下の数全体の集合」のこと
 $$[a,b]$$

つまり開区間 $(a,b)$ は値 $a$ を元に持たないが、閉区間 $[a,b]$ は $a$ を元に持つ。

片側開区間で片側閉区間として $(a,b]$ みたいな書き方をすることもある。$a$ は含まないが $b$ は含む区間である。一瞬誤植に見える。


[高校数学の美しい物語
開区間，閉区間の意味と関連する話題](https://manabitimes.jp/math/1183)


### 写像

「ある集合 $A$ の元を別の集合 $B$ の元に対応させる規則」を写像と呼ぶ。写像 $f$ が $A$ から $B$ に元を写すとき、$f:A \longrightarrow B$ みたいな表記をする。$A$ と $B$ は同じ集合でも包含関係でも良い。同一の集合のとき変換とも呼ぶ。

関数や微分や畳み込みや何やらはすべて写像である。特に合成写像や全射・単射などの概念は理解しておくと便利である。
同型写像やカーネルも重要な概念ではあるが必要になってからでよい。

[写像 東北大学情報科学研究科数学教室](https://www.math.is.tohoku.ac.jp/~obata/student/subject/file/2018-4_shazo.pdf)

### ベクトル空間(線形空間、線型空間)

ベクトル空間を理解する前にまず「体」と呼ばれる集合を理解しなければならない。それにベクトル空間の定義はどこを見ても同様な難解さかもしれない。

厳密性をあえて排除して説明する。ベクトル空間とは、そこに属する元（ベクトル）同士で足し算したものが同一空間内の別の元（ベクトル）となり、元（ベクトル）に数字を掛け算して伸ばしたり縮めたりできる集合である。「元同士で足し算したものが同一空間内の別の元となる」とき、空間内で足し算を定義できる、演算が閉じていると表現することがある。

また、足しても変化を及ぼさない元（ゼロベクトル）の存在と、任意の元に対する逆元の存在（ベクトル $A$ に対する $-A$ のこと）、それといくつかの足し算のルールを含めてベクトル空間が定義される。

「長さ」を定義できずともベクトル空間の定義を満たす。内積や外積も必要ではない。定義が抽象的なので、思いもよらないものがベクトルとして扱える。例えば適切に定義された空間において適当な関数がベクトル空間を張ることがある。三角関数や指数関数がベクトルとして扱われることは多い。

馴染みがなければ難解なので理解を後回しても良いが、ディープラーニングは線形写像と非線形写像を繰り返すことで任意の関数を近似することが根幹なので、線形とは何なのか時間をかけて学ぶことに損はないと思う。

[一般の線形空間 東京電機大学](https://www.cck.dendai.ac.jp/math/support/ch5-supp/%E4%B8%80%E8%88%AC%E3%81%AE%E7%B7%9A%E5%BD%A2%E7%A9%BA%E9%96%93.pdf)

- 補足：体の定義
    
    [代数学の基本｜群・環・体の定義と具体例をゼロから解説](https://math-note.xyz/algebra/basics-of-algebra/)

### ベクトル

### ベクトル積(外積)

### スカラー積(内積)

### 行列

### 行列の演算

#### 和、差

#### 積

### 行列式

### 逆行列

### トレース

### 固有値

### 二次形式

### テンソル(多重線形写像)

## 関数

### 微分

### 積分

### 偏微分

### 三角関数

### 指数関数

### 対数関数

### 不連続関数

### 合成関数

### 逆関数

## ベクトル解析

### 勾配(gradient)

### 発散(divergence)

### 回転(rotation)

## 確率・統計

### 場合の数

### 確率(不連続)

### 確率(連続)

### 確率変数

### 条件付き確率

### 標本

### 期待値

### 分散

### 分布

#### ガウス分布、正規分布

#### ベルヌーイ分布

#### 二項分布

#### 多項分布

### 相関

### 相関行列

## ベイズ統計

## エントロピー

## 超関数

## 畳み込み
目を大事にしよう！

# はじめに
うーん、自分の文字ってこんな汚かったっけ？周りの景色がぼやけるんだけど！？とか思ったことは誰もが一度は思ったことはあるでしょう。そのたび目をこすり元に戻そうとするでしょう。しかし大体それらは目の疲れからくるものだと思います。疲れている目にさらに物理的に攻撃だなんて、目がかわいそうとは思いませんか？この記事では目の疲れの原因、対処方法を書いていこうと思います。
# 原因
原因はさまざまあります。一つ目は目の酷使です。例えば、長時間のパソコン作業、近距離でものを見たりすることです。また、眼鏡やコンタクトが合っていないことも原因です。二つ目は目の乾きです。例えばパソコンなどのディスプレイを長時間見続けると、目の酷使のほか、画面を凝視するため、まばたきの回数が減り、目が乾いた状態となりやすく、さらに目が疲れやすくなる、VDT（Visual Display Terminal）ストレスというものがあります。要するにスマホやパソコンの見過ぎということですね。
# 対策
 VDT（Visual Display Terminal）作業などの目の疲れは単純ですが目薬などが効果的！目薬で目の乾燥を防ごう！！！
ほかには目を閉じる、温めるなどがあります。原因に比べ対処方法は原始的をいうか、、、結局画面を見るのを減らすしかないみたいですね。
 IT系の職業に就くと体に支障をきたすことが少なからずあると思います。現在自分は腰が痛く、どうしようか考えている最中です。長生きし、不自由ない生活を過ごすためにも健康には気を使わないといけませんね！！
これだけはしておけ！Qiita投稿前のセルフレビューリスト

# 初めに

記事を投稿する前にこのレビューリストを見てセルフレビューしよう！
Markdownでコピーして、各自のVScodeでプレビューすると、チェックボックスも使えます。[Github](https://github.com/tomo1227/markdown-review-lists)にも載せています。

:::note warn
Markdownの書き方がなっていない、スタイルがめちゃくちゃな記事をよく見かけます。特に**フロントエンジニア**などはよく見られるので、気をつけてください。
:::

# Markdownレビューリスト

## タイトル

- [ ] 妥当なタイトルをつける (たとえば、初心者向けなのか?プロフェッショナル向けなのか?などターゲットを意識する)
- [ ] 具体的で簡潔なタイトル
- [ ] 強調したい内容は基本的に【】でくくる。(【3分で習得】など)

## タグ

- [ ] 不要なタグはつけない (無関係なタグなど)
- [ ] 正しいタグをつける (〇Python ✕ python)
- [ ] ターゲットがなるべく多いタグをつける (〇 Python(77315))

## 本文

### スタイル

- [ ] 見出しは`###`レベル3まで → ネストが多い場合は記事を分ける
- [ ] styleの統一 (path名は**bold**, メソッド名は*イタリック*で統一するなど)
- [ ] 長文より短文の方が見やすい。**ポエム** にしない。
- [ ] 読みやすさを確認 (パッと見てみて強調してる箇所が目に入ってくるかなど。)
- [ ] <font color='red'>特に強調したい箇所</font>は`<font color='red'>色をつけるという手もあります</font>`で色をつける
- [ ] 段落構成(限定公開で全体表示したときに右サイドバーの目次で確認。)
- [ ] 見出しレベルが連続している。`#`の次に`###`を使わない。
- [ ] 強調で`#`を使わない
- [ ] 上から下へと**順番に**読める
- [ ] 改行、空白、スペルミスのチェック
- [ ] MarkdownのLinterでチェックしている
- [ ] 記事内リンクは`(hoge)[#hoge]`でつける
- [ ] ライブラリ名やツール名を使う際は、HPなどのリンクを追加する。(e.g. [Golang](https://go.dev/))
- [ ] 上記以外の外部のリンクは基本的にまとめて参考文献へ。(飛んだら戻ってこなくなる可能性がある)


### 図表

- [ ] [LICEcap](https://www.cockos.com/licecap/)でGIFを撮影する
- [ ] [draw.io](https://app.diagrams.net/)や[Figma](https://figma.com/ja/)で図を書く
- [ ] 適切な図表が使われている。読み込み失敗などしていない。
- [ ] 箇条書きは表にした方が見やすい可能性がある。
 
### ソースコード

- [ ] 正しいシンタックスハイライトをつける
- [ ] コードが記事通りコピペして動作する
- [ ] コードが長いときは`<details><summary>title</summary><div>contents</div></details>`で折りたたむ。
- [ ] コードに記載されているファイル名が正しいのか。(カレントディレクトリを統一する)
- [ ] Terminalの場合は`shell-session:terminal`を付ける(terminalやconsoleもできるが、互換性を考えて、shell-sessionに統一。**プロンプト付けない場合** は`batch`など)
- [ ] Terminalのプロンプトを`$`に統一。(`%`はシンタックスハイライトがつかない)
- [ ] プレーンテキストのシンタックスハイライトは何もつけない。(○ `:hoge.txt`　×　`text:hoge.txt`)
- [ ] フロントなど[CodePen](https://codepen.io/)を使った結果とコードが見やすいなら利用する

## 参考文献、注釈

- [ ] [注釈記法](https://qiita.com/nishina555/items/39d88361157545d12a94) を利用する
- [ ] 注釈記法が面倒な場合は、`[title](url)`で最後にまとめておく
mindの研究 その52

# 概要
mindが、謎なので調べてみた。
練習問題やってみた。

# 練習問題
mindでweb serverを書け。

# 方針
- socketlib使う
- ポート40001
- 404を返す

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9e8b428b-9c76-34d7-67b8-6386f4b2047d.png)


# サンプルコード

```
エラー検査とは
　エラー？
　ならば
　　エラー文字列で　重大エラー
　つぎに
。

ミタとは
　変換後は　文字列実体
　変換後を　クリア
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後を　返すこと
。

レスポンスとは
　変換後は　文字列実体
　変換後を　クリア
　変換後に　「HTTP/1.1 404 Not Found」を　追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後を　返すこと
。

メインとは
　ホスト名は　文字列
　ポート番号は　変数
　待ちソケットは　変数
　データソケットは　変数
　エラーコードは　変数
　文字列１は　文字列
　「localhost」を　ホスト名に　入れ
　40001を　ポート番号に　入れ
　「ホスト名 」を　表示し　ホスト名を　表示し　「 、」を　表示し　ポート番号を　数値表示し　「 番ポートで待つ。」を　一行表示する
　ホスト名と　ポート番号と　１個で　ｌｉｓｔｅｎし　待ちソケットに　入れ　エラー検査し
　「ｌｉｓｔｅｎの後」で　このメッセージでスタック検査し
　「ｌｉｓｔｅｎ完。待ちソケット = 」を　表示し　待ちソケットを　数値表示し　改行する
　ここから
　　「ａｃｃｅｐｔします」を　一行表示し
　　待ちソケットで　ａｃｃｅｐｔし　データソケットに　入れ
　　エラー？
　　ならば
　　　「エラー：」を　エラー出力し　エラー文字列を　一行エラー出力し
　　　打ち切り
　　つぎに
　　「ａｃｃｅｐｔ完。データソケット = 」を　表示し　データソケットを　数値表示し　改行する
　　ここから
　　　データソケットから　ハンドル指定で一行読み出し　文字列１に　入れる
　　　データ終り？
　　　ならば
　　　　「[EOF]クライアントが終了しました。」を　一行表示する
　　　　打ち切り
　　　つぎに
　　　文字列１が　「」に　等しい文字列
　　　ならば
　　　　「クライアントが終了しました。」を　一行表示する
　　　　打ち切り
　　　つぎに
　　　「データ ＝ 」を　表示し　文字列１を　一行表示し
　　繰り返し
　　レスポンスを　文字列１に　入れ
　　文字列１を　データソケットに　ハンドル指定で一行書き込み
　　「データソケットをクローズします」を　一行表示する
　　データソケットを　ハンドル指定でクローズする
　　「待ちソケットをクローズします」を　一行表示する
　　待ちソケットを　ハンドル指定でクローズする
　　打ち切り
　繰り返し
　「終わります。」を　一行表示する
。





```

# 実行結果

```
>webserver1
ホスト名 localhost 、40001 番ポートで待つ。
ｌｉｓｔｅｎ完っこう。待ちソケット = -552
ａｃｃｅｐｔします
ａｃｃｅｐｔ完。データソケット = -556
データ ＝ GET / HTTP/1.1
データ ＝ Host: localhost:40001
データ ＝ Connection: keep-alive
データ ＝ sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"
データ ＝ sec-ch-ua-mobile: ?0
データ ＝ sec-ch-ua-platform: "Windows"
データ ＝ Upgrade-Insecure-Requests: 1
データ ＝ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
データ ＝ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
データ ＝ Sec-Fetch-Site: none
データ ＝ Sec-Fetch-Mode: navigate
データ ＝ Sec-Fetch-User: ?1
データ ＝ Sec-Fetch-Dest: document
データ ＝ Accept-Encoding: gzip, deflate, br
データ ＝ Accept-Language: ja,en-US;q=0.9,en;q=0.8
データ ＝ Cookie: lb:user_data=eyJlbWFpbCI6bnVsbCwiaGV4X2NvbG9yIjoiIzYwQTVGQSIsImlkIjoibXJ3M200YW9qN2l6ajdraGg1NTVtcWlvNWl0aGlhN3kiLCJuYW1lIjpudWxsfQ==
クライアントが終了しました。
データソケットをクローズします
待ちソケットをクローズします
終わります。

```

以上。
BigQueryで取ってきた値でループする

# BigQuery取ってきた値でループ処理したい
[Google Cloud Champion Innovators Advent Calendar 2023](https://adventar.org/calendars/9217) 16日目です。
（ん？もう12/25？おっかしいなぁ。そんなことはさておきです。はい。すいません。）
BigQueryのクエリ結果を変数に入れて、ループ処理したいときって無いですか？
複数列を取ってきて、やりたいなんてことはちょいちょいあります。
そんなときに **Array** と **Struct** を便利に使ってやってみましょう！
今回はbigquery-public-data.austin_bikeshareを例にやってみたいと思います。

# まずは変数の指定
DECLAREのところで変数を指定します。
複数行を入れるためにArrayを指定して、その中に複数列を入れるためにStructで構成します。
今回の場合はstation_id,name,statusの3つの列を入れていきます。
```SQL:variable.sql
-- クエリ結果を入れる変数
DECLARE array_struct ARRAY<STRUCT<station_id INT64, name STRING, status STRING>>;
```
# 変数に値を入れてみる
変数に値を入れていきます。
SQLの実行結果を変数に入れるのですが、変数の方に合わせる必要があるので実行結果も同じように **Array** と **Struct** にする必要があります。
`bigquery-public-data.austin_bikeshare.bikeshare_stations`のテーブルの値を入れていきます。

```SQL:variable.sql
-- クエリ結果を入れる変数
DECLARE array_struct ARRAY<STRUCT<station_id INT64, name STRING, status STRING>>;

-- クエリ結果を変数に入れる
SET array_struct = (
  SELECT
    ARRAY_AGG(
      STRUCT(
        station_id,
        name,
        status
      )
    )
  FROM
    `bigquery-public-data.austin_bikeshare.bikeshare_stations`

  );

-- 変数に入ったものを見てみる
SELECT
  array_struct;
```
実行結果
![スクリーンショット 2023-12-25 070435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49108/a74b3540-ba36-256e-cb91-c5f323f86594.png)

ここでわかるのですが、変数は複数の値を持つことはできないので、複数の値をなんとか1つのところに入れています。
簡単に言うと小袋で分かれているポッキーが1つの箱に入って、またダースの箱に入って、そのダースの箱を1つの段ボールに入れているマトリョーシカみたいな感じで入れていると考えればわかりやすいかと。（わかりやすいか？）

# 結果を1つずつ取り出してみる
では、結果を１つずつ取り出してみましょう。
変数に入れたデータ分だけ、ループをまわすのでその数をさらに変数に追加していきます。
今回は1つずつ取り出して、さらにそれを変数に格納してみます。

```SQL:variable.sql
-- クエリ結果を入れる変数
DECLARE array_struct ARRAY<STRUCT<station_id INT64, name STRING, status STRING>>;

-- array_structから取り出した値を入れる変数
DECLARE array_struct_row STRUCT<station_id INT64, name STRING, status STRING>;

-- array_structの長さを入れる変数
DECLARE loop_cnt INT64;

-- ループ用の変数
DECLARE i INT64 DEFAULT 0;

-- クエリ結果を変数に入れる
SET array_struct = (
  SELECT
    ARRAY_AGG(
      STRUCT(
        station_id,
        name,
        status
      )
    )
  FROM
    `bigquery-public-data.austin_bikeshare.bikeshare_stations`
  );

-- 変数に入ったものを見てみる
SELECT
  array_struct;

-- 変数array_structの長さをloop_cntに入れる
SET loop_cnt = ARRAY_LENGTH(array_struct);

-- ループ開始、loop_cnt分回す
WHILE loop_cnt > i
  DO
    -- 1行ずつ入れていく
    SET array_struct_row = (
      SELECT
        array_struct[offset(i)]
    );
  
    -- 確認用
    SELECT
      array_struct_row;
    
    -- 列を取り出したいときはこんな感じで、たとえばstation_idの場合
    SELECT
      array_struct_row.station_id;

    -- 次の行のために1つ増やす
    SET i = i + 1;
END WHILE;
```

# 最後に
こんな感じでクエリ結果を利用してループをまわすということができます。
僕自身はEXECUTE IMMEDIATEを利用してクエリ結果をファイルに吐き出す場合に、条件やファイル名などを一気に取ってきて、1つずつ処理させたりするときに利用しています。
では、2024年も楽しいBigQueryライフを！！！
アドベントカレンダーに初参加の感想

# はじめに
この記事は2023年度の振り返りです。

# 初参加の感想
今回、初Qiitaからの初アドベントカレンダー参加でした。
アドベントカレンダーも12/4から参加で、急ピッチで色々な振り返りの記事を書いていました。
結果、無事に完走はできたものの結構きつい作業でした。
ただ、いい刺激にはなったので可能な範囲今後もイベントごとには参加していきたいと思います。

# さいごに
qiitaも初でしたが、利用ユーザー数が多いこともありコメントにて指摘も頂き自分のためにもなったり、今回のイベントなどが色々開催されていたりと嬉しいことばかりでした。
今後はqiitaを中心に活動してみようかと思います。
勉強会での小話6

# はじめに

この記事は2023年度の振り返りです。

こちらの続きとなります。

https://qiita.com/youfuku/items/567b3cf510bf40cb3371

問題を解いてる時の実話を元に、作成しております

# 勉強会内の小話

講師：よし、最後のリレーションの問題だ！
講師：「アイシールド21」と同じ作者が書いた作品全てを返すリレーションを作ってみよ！

初学者達：はい！

初学者達：これでどうでしょう！
```ruby
class Comic < ApplicationRecord
  has_many :kaku, foreign_key: 'book_id', class_name: 'Write'
  has_many :kaita_hito, through: :kaku, source: :hito
  has_many :onaji_sakusya, through: :kaita_hito, source: :kaita_manga
end
```

```ruby
class Write < ApplicationRecord
  belongs_to :hito, foreign_key: 'user_id', class_name: 'Author'
  belongs_to :manga, foreign_key: 'book_id', class_name: 'Comic'
end
```

```ruby
class Author < ApplicationRecord
  has_many :kaita, foreign_key: 'user_id', class_name: 'Write'
  has_many :kaita_manga, through: :kaita, source: :manga
end
```

講師：お？じゃぁ、確認してみよう

```ruby
comic = Comic.find_by(name: 'アイシールド21')
comic.onaji_sakusya
```

```sql
SELECT `comics`.* 
FROM `comics` 
INNER JOIN `writes` ON `comics`.`id` = `writes`.`book_id` 
INNER JOIN `authors` ON `writes`.`user_id` = `authors`.`id` 
INNER JOIN `writes` `kakus_onaji_sakusya` ON `authors`.`id` = `kakus_onaji_sakusya`.`user_id` 
WHERE `kakus_onaji_sakusya`.`book_id` = 3
```

```ruby
=> 
[#<Comic:0x00007f185bb75280
  id: 3,
  name: "アイシールド21",
  created_at: Sat, 23 Dec 2023 02:56:25.513233000 UTC +00:00,
  updated_at: Sat, 23 Dec 2023 02:56:25.513233000 UTC +00:00>,
 #<Comic:0x00007f185bb75140
  id: 4,
  name: "ワンパンマン",
  created_at: Sat, 23 Dec 2023 02:56:25.520151000 UTC +00:00,
  updated_at: Sat, 23 Dec 2023 02:56:25.520151000 UTC +00:00>]
```

講師：お？素晴らしい！一発合格じゃないか！完璧にマスターしたんじゃないか？

初学者達：フローは微妙なんですよね。。。

講師：なるほど。フローにするとこんな感じだな

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/4033f067-3c44-7e9c-8541-2090f9e84cb7.png)

初学者達：余計わかんねーよ！！

講師：すまん。自分も書いててこんがらかってきた。ただ、事前にリレーションを書いておくことで、呼び出すときが楽になったりするので使うと思うリレーションは書いていた方が楽だぞ

初学者達：わかりました！

# さいごに
無事に開催の雰囲気の記事がかけてよかったです。
最後までご拝読されていた方は、最後までお付き合い下さいましてありがとうございました。
こんな感じで日々勉強会を開催してたりします。
自分は初学者に対しては、ベストプラクティスを教えるより、多くの手段を学んで頂きたいと考えております。その上で、場面に応じたベストプラクティスを自分たちで模索して利用して言ってくれればと思っております。
少し上から目線になってしまいましたが、自分も日々精進が必要なので、今後も色々なものをアウトプットしていきたいと思います。
AxumでリクエストボディのOptionalかつNullableなフィールドを区別して処理する方法

REST APIで、リクエストボディ（JSON）の特定のフィールドについて、値あり・ `null` ・フィールドなしを区別して処理したい場合があります。

RustのWebアプリケーションフレームワーク[Axum](https://github.com/tokio-rs/axum)でこれらを区別する際に、少し工夫が必要だったのでまとめます。

## 検証環境

```toml
[dependencies]
axum = "0.7.2"
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
tokio = { version = "1.35.1", features = ["full"] }
```

## コード

```rust
pub struct OptionalNullableField<T>(pub Option<Option<T>>);

/// OptionalNullableField<T>のフィールドまたはそれを含むstructに`#[serde(default)]`をつけると、
/// リクエストにフィールドが存在しないときに`OptionalNullableField(None)`になる
impl<T> Default for OptionalNullableField<T> {
    fn default() -> Self {
        Self(None)
    }
}

pub struct OptionalNullableFieldVisitor<T>(PhantomData<T>);

/// リクエストにフィールドが存在するときで、
/// 値がnullのときは`OptionalNullableField(Some(None))`、
/// null以外の値がセットされているときは`OptionalNullableField(Some(Some(value)))`となる
impl<'de, T> Visitor<'de> for OptionalNullableFieldVisitor<T>
where
    T: Deserialize<'de>,
{
    type Value = OptionalNullableField<T>;

    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_str("null or T")
    }

    fn visit_none<E>(self) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(OptionalNullableField(Some(None)))
    }

    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        T::deserialize(deserializer).map(|v| OptionalNullableField(Some(Some(v))))
    }
}

impl<'de, T> Deserialize<'de> for OptionalNullableField<T>
where
    T: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_option(OptionalNullableFieldVisitor(PhantomData))
    }
}
```

このようなデシリアライザを実装し、以下のようにリクエスト構造体を定義すると、使用できます。

```rust
#[derive(Deserialize)]
struct UpdateUser {
    #[serde(default)]
    username: OptionalNullableField<String>,
}

async fn update_user(Json(payload): Json<UpdateUser>) -> impl IntoResponse {
    match payload.username.0 {
        Some(Some(v)) => v, // 値がセットされているとき
        Some(None) => "null".to_string(), // nullがセットされているとき
        None => "none".to_string(), // フィールドが存在しないとき
    }
}
```
スケールアウトするのか、しないのか、PolarDB for MySQL パフォーマンス ホワイトペーパーを読み解いて、グラフを作って考察してみた

# 結論
PolarDB for MySQL 8.0.2 パフォーマンス ホワイトペーパーから読み解くと、クラスタの読み取りノードを<INS>**1台から8台**</INS>にスケールアウトとすると、読み取り性能(QPS)について<INS>**おおよそ4倍程度**</INS>の性能アップが見込めます。

ホワイトペーパーの概要については、[こちらの記事](https://qiita.com/Max-Masato/items/39364bad327b44ac841f)をご覧下さい。

<INS>**スケールアップの比較サマリ**<INS>
 
| クラスタ台数 | 1 台 | 2 台 | 4 台 | 8 台 |
| :--: | :--: | :--: | :--: | :--: |
| 伸び率(絶対値) | 1台を基準に | 約1.3 ～ 1.5倍 | 約2.0 ～ 2.3倍 | 約3.6 ～ 4.4倍 |

下記のグラフから、クラスタノードを追加するたびにほぼリニアに性能が伸びているのが確認できます。
純粋なQPSの絶対値だと、8ノード構成で、Sysbench - 512 Threadsのテストが一番、性能が出ていますが、ただ128 Threads以上では、伸び率が低下しており、QPSの絶対値の伸びもあまりありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637906/b71aebf7-e1ee-0f0d-6ecb-b1db2d993c83.png)


:::note info
Queries per second (QPS):：INSERT、SELECT、UPDATE、および DELETE ステートメントを含む、データベースで 1 秒あたりに実行される SQL ステートメントの数。
今回のテストは、"Test results of read-only performance"となります。
:::

:::note info
Sysbenchのテストの環境や前提条件、ツールの解説については、[こちらのページ](https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/oltp-performance-test?spm=a2c63.p38356.0.0.7dbdad12JHVyBt
)をご覧ください

:::


# 考察1 : 負荷に対するQPSのリニアな向上

Sysbenchの同時接続数の設定であるThreadについて注目すると、16 Threads、32および64Threadsの一部については、リニアなQPSの伸びになっている。

ただし、128Threads以降については、過負荷状態なのか、伸びも低くむしろQPSが低下している。
また、32 Threadsの7,8ノードの追加では、Sysbench側の負荷が足りない低負荷状態になっていると推測され、CPUとMemoryが余っているのではないかと推測します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637906/48d678c8-2048-6183-37d5-f343e0afd642.png)


以上の事から、今回のテスト条件（テストシナリオとHW構成）では、32 Threadsから64 Threadsの間あたりが、最も処理効率が良いのではないかと考察します。


# 考察2 : Read Only Node追加に伴うQPSの伸び率の変化

どのテスト・シナリオを見ても、ほぼノード台数の追加にリニアに伸びており、一部のテストが低負荷になってしまっているシナリオを除けば、特に懸念はないと考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637906/2b3458f1-da1c-492e-e31d-b2b23bfc6396.png)


# 最後に
改めて、パフォーマンス ホワイトペーパーを見て、QPSが絶対値ベースで作成された資料は、実態がつかみやすいと実感した。

以下、パフォーマンステスト内容について、もう少しここを改良してもらえたら、という提言です。
1. このテストでは、各ノードのスペックは4コア、16GBと言う条件でしたが、利用されているElastic Compute Service（ECS）の ecs.c5.4xlargeのインスタンスタイプだと、16コア、32GBのスペックのはずなので、この違いはなんだろうかというのと、フルスペックでテストを実施してもらえると概算見積もりにも使いやすいテスト結果になると考えます。
1. PolarDB for MySQLの場合、16台までスケールアウトできるはずなので、テストも16台までスケールアウトして実施して欲しかった。

# 参考文献

Performance test results of PolarDB for MySQL 8.0.2 (Cluster Edition)

https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/performance-test-results-of-polardb-for-mysql-8-0-2-cluster-edition

<BR>
OLTP performance test (英語) ※テストの環境や前提条件、ツールの解説

https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/oltp-performance-test?spm=a2c63.p38356.0.0.7dbdad12JHVyBt

<BR>
PolarDB for MySQL に関するパフォーマンス ホワイトペーパー(英語)

https://www.alibabacloud.com/help/en/polardb/polardb-for-mysql/performance-white-paper-4/
AWS Secrets Managerを使って本気でAWSアカウントを守る

# はじめに
この記事はDevOps on AWS大全の一部です。
DevOps on AWS大全の一覧は[こちら](https://qiita.com/tech4anyone/items/b06f88035d27c6ef13b2)。

この記事ではAWS Secrets Managerに関連する内容を超詳細にまとめています。

具体的には以下流れで説明します。

- AWS Secrets Managerとは
- AWS Secrets Managerの仕組み
- AWS Secrets Managerの活用
- AWS Secrets Managerのベストプラクティス

AWSの区分でいう「Level 200：トピックの入門知識を持っていることを前提に、ベストプラクティス、サービス機能を解説するレベル」の内容です。

# この記事を読んでほしい人
- AWS Secrets Managerがどういうサービスか説明できるようになりたい人
- AWS Secrets Managerを採用するときのベストプラクティスを説明できるようになりたい人
- AWS Certified DevOps Engineer Professionalを目指している人

# AWS Secrets Managerとは
AWS Secrets Managerは、AWSのサービスの一つで、機密情報（シークレット）を安全に管理するためのツールです。
シークレットとは、データベースやAPIなどにアクセスするためのパスワードやトークンなどの情報のことです。
AWS Secrets Managerを使うと、シークレットを暗号化して保存し、アクセスポリシーを設定したり、自動的にローテーションしたりすることができます。

# AWS Secrets Managerの仕組み
AWS Secrets Managerは、以下のような仕組みでシークレットを管理します。

## シークレットの保存
シークレットを作成するときに、シークレットの名前や値、説明、タグなどのメタデータを指定します。シークレットの値は、KMS（キーマネジメントサービス）で暗号化されて保存されます。

また、シークレットには、アクセスポリシーを設定することができます。
アクセスポリシーは、IAMのロールやユーザーなど、どのような主体がシークレットにアクセスできるかを定義するものです。
アクセスポリシーを設定することで、よりセキュアにシークレットを保存できるようになるので適切な設定をすることが大切です。

## 自動ローテーション
シークレットには、ローテーションルールを設定することができます。
ローテーションルールは、シークレットの値をどのくらいの頻度で変更するかを定義するものです。
ローテーションは、AWS Lambda関数を使って実行されます。
実際の挙動としてはシークレットの値を新しいものに変更し、それに合わせて関連するサービスやアプリケーションの設定も更新します。

## シークレットの呼び出し
シークレットにアクセスするには、AWS SDKやCLIなどを使って、AWS Secrets ManagerのAPIを呼び出します。
APIでは、シークレットの名前やバージョンなどを指定して、シークレットの値を取得できます。
取得したシークレットの値は、メモリ上で一時的に保持されます。ディスクやログなどに書き込まれることはありません。

## AWS Secrets ManagerとSSM Parameter Storeの比較
AWS Secrets ManagerとSSM Parameter Storeは、どちらもAWSのサービスで、構成データや機密情報を管理するためのツールです。
しかし、両者には以下のような違いがあります。

| 項目 | AWS Secrets Manager | SSM Parameter Store |
| --- | --- | --- |
| 暗号化 | KMSで暗号化される | KMSで暗号化される（オプション） |
| アクセスポリシー | シークレットごとに設定可能 | パラメータごとに設定可能 |
| ローテーション | 自動的に実行可能 | 手動で実行する必要がある |
| API呼び出し回数制限 | 700回/秒 | 40回/秒 |
| コスト | 有料| スタンダードは無料 |

試験対策でいうと、シークレットを自動ローテーション、ときたらSecrets Managerです。

# AWS Secrets Managerの活用
AWS Secrets Managerは、以下のような場面で活用できます。

## シークレットを安全に保存したい場合
AWS Secrets Managerは、シークレットを暗号化して保存し、アクセスポリシーで制限することで、シークレットの漏洩や不正利用を防ぐことができます。

## シークレットを自動的にローテーションしたい場合
AWS Secrets Managerは、ローテーションルールを設定することで、シークレットの値を定期的に変更することができます。これにより、シークレットが古くなったり、盗まれたりするリスクを低減することができます。

## シークレットを簡単に管理したい場合
AWS Secrets Managerは、シークレットの作成や更新や削除などをGUIやCLIなどで行うことができます。また、シークレットにタグや説明などを付けることで、シークレットの分類や検索も容易になります。

# AWS Secrets Managerのベストプラクティス
AWS Secrets Managerを使うときには、以下のようなベストプラクティスに従うとよいでしょう。

| ベストプラクティス | 説明 |
| --- | --- |
| シークレットの最小権限原則 | シークレットにアクセスできる主体は、必要最小限に限定すること。不要な主体にアクセス権を与えないこと。 |
| シークレットのローテーション | シークレットの値は、定期的にローテーションすること。ローテーションの頻度は、シークレットの重要度やリスクに応じて調整すること。 |
| シークレットの命名規則 | シークレットの名前は、一意でわかりやすくすること。シークレットの種類や用途や環境などを表す接頭辞や接尾辞を使うこと。 |
| シークレットのメタデータ | シークレットには、タグや説明などのメタデータを付けること。メタデータは、シークレットの管理や監査やコスト割り当てなどに役立つこと。 |


# まとめ
この記事ではAWS Secrets Managerに関連する内容を超詳細にまとめました。

- AWS Secrets Managerとは
- AWS Secrets Managerの仕組み
- AWS Secrets Managerの活用
- AWS Secrets Managerのベストプラクティス

以上でDevOps大全 on AWSは連載終了です。
2か月にわたり読んでくださった皆様ありがとうございました。

# 次回予告
DevOps実践編 on AWSと題してDevOpsエンジニアが実プロジェクトでどのような思考を経てアーキテクチャを決めているのかを解き明かしていく内容で連載をスタート予定です。
Googleカレンダーの予定をSlackに連携する with GAS


## やりたいこと

毎日特定の時間になったら、Googleカレンダーに登録されている当日の予定を取得し、指定のSlackチャネルに通知する。
予定が複数あった場合も、すべて表示する。

### 完成イメージ

![スクリーンショット 2023-12-25 063305.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243130/d9bd45d4-f631-87b0-1d0c-a87d592e0ed5.png)

## 悩んだところ

### GASのSlackAppライブラリの問題

「GAS Slack 連携」で検索して出てくる多くの記事で`SlackApp`(M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO)というライブラリを使用する方法が紹介されています。
しかし2023/11/8時点では、既に使用できなくなっていました。(Slackに通知が飛ばない)

代替手段として、SlackのWebhookを使用する方法とSlack APIを使用する方法を検討した結果、以下の理由で最終的にSlack APIを使用しました。


### Webhookの問題点

Webhookの方がSlack APIより簡易的に連携で来たのですが、Webhookの場合に以下のことが出来ませんでした。

**複数行の引用ブロックができない**

通常Slackでは、引用ブロックを複数行にしたい時に`Shift + Enter`で実現出来ます。
しかしWebhookの場合は、これの実現手段がありません。
Slack APIでは`>>>`とすることにより、引用ブロック内での改行が実現出来ました。

**URLをハイパーリンク化できない**

WebhookではURLをそのまま送信しても、ただの文字列として扱われてしまいます。
Slack APIではURLを`< >`で囲むことにより、ハイパーリンクとして認識させることが出来ます。
例) `<https://example.com>`

## 実際のコード

```javascript
function execute() {

  // Slackボットがメッセージを投稿するチャンネルを定義する
  const channelId = "XXXXXXXXXX"; // 通知したいSlackのチャンネルID

  // SlackAPIで登録したボットのトークンを設定する
  const token = 'xoxb-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
  const url = "https://slack.com/api/chat.postMessage";

  // 実行ユーザーのデフォルトであるGoogleカレンダーを取得する
  const myCalendar = CalendarApp.getDefaultCalendar();

  // Googleカレンダーの予定取得する日を設定する
  const calDate = new Date();

  // 今日1日のGoogleカレンダーのイベントを取得する
  const myEvent = myCalendar.getEventsForDay(calDate);

  // イベントがなかったら終了
  if (myEvent.length === 0) {
    console.info('イベント無し');
    return;
  }

  // Slackに通知するGoogleカレンダーの予定メッセージを作成
  const blocks = [];
  blocks.push(createMessage(`本日の予定です`));

  for(let i = 0; i < myEvent.length; i++){
    let startH = myEvent[i].getStartTime().getHours();
    let startM = myEvent[i].getStartTime().getMinutes();
    if(startM < 10) startM = '0' + startM;
    let endH = myEvent[i].getEndTime().getHours();
    let endM = myEvent[i].getEndTime().getMinutes();
    if(endM < 10) endM = '0' + endM;

    const timeString = `${myEvent[i].getStartTime().getMonth() + 1}/${myEvent[i].getStartTime().getDate()}　${startH}:${startM} ～ ${endH}:${endM}`;
    const locationString = myEvent[i].getLocation() ? `<https://www.google.com/maps/search/?api=1&query=${myEvent[i].getLocation()}|${myEvent[i].getLocation()}>` : '';

    blocks.push(createMessage(`
>>> *${myEvent[i].getTitle()}*
⏰ ${timeString}
📍 ${locationString}
📝 ${myEvent[i].getDescription()}
`
    ));
  }

  const headers = {
    "Content-Type": "application/json; charset=utf-8",
    "Authorization": "Bearer " + token
  };
  const payload = {
    "channel": channelId,
    "blocks": blocks
  };
  const params = {
    "method": "POST",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  UrlFetchApp.fetch(url, params);

  console.info('Success');
}

/* メッセージを作成 */
function createMessage(message) {
  return {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": message
      }
    };
}
```

### チャンネルIDとAPIトークンの取得方法

それぞれ以下の記事を参考にして、取得してください。

- チャンネルID

https://zenn.dev/dashi296/articles/4324507780a3cf

- APIトークン

https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21
25記事を書きました

## はじめに
　今回「日々の隙間で何かを学ぶ 」という題材のもと、Qiitaアドベントカレンダーで25本の記事を作成しました。最終日である本日は、これらの記事を書くにあたり、考えていたことやネタを思いつくためにやったことをまとめました。最後まで読んでいただければ幸いです。

## いつもと違うことをやってみる
　私は、wordpressで自身のサイトを作成してブログ記事を書いていました。そこでは、主にSEOメインの集客記事を書いてます。文章を書くことにはいまだに苦手意識はありますが、ブログ記事の作成は多少慣れていました。
　Qiitaの記事では、SEOを意識せずに記事を書くことをまず初めに決めました。その理由としては、以下があります。
 - いつもと違うことをやってみる
 - SEO記事は構成やネタを考えるのに時間が書かかる
 - 自身のブログと比べて、結果の分析などができない
 - 記事をたくさん書く必要がある

　いつもと違う感じで記事を書くことで、よりアイディアやネタの幅が広がったと感じています。
 
## 視野を広げる
　Qiitaはエンジニア向けの技術系の記事を書かないといけないということもあり、書けるネタがあまりありませんでした。そのため、この企画を始めてからは常にネタを探していました。自分の既に知っていることや過去体験をあまり書きたくなく、初めて知ったことや調べてみたこと、自分以外が書かないようなことを軸としてネタを集めました。
 　勉強中や仕事中に疑問に思ったことや初めて知ったこと、いつもは意識しなかったが詳しく調べてみたことで記事が書けないかと探していました。視野を広げてアンテナを張ることで、小さなアイディアをたくさん生み出すことができました、
 
## 他の方の記事を読んでみる
　今回の企画で初めてQiitaの記事を書いたことにより、他の方が書いたQiita記事も読者目線だけでなく、作者目線で見るようになりました。Qiitaではどのような記事が書かれているか、どのような記事が人気のあるかを知るためにとりあえず記事をたくさん読みました。やはり、エンジニア向けの技術系の記事ということもあり、自分は書けないような記事がほとんどでした。そんな中で、自分の書けること、独自の目線を意識してネタ集めをしていました。


## おわりに
　今回は毎日記事を投稿するという企画に参加して、たくさんのものを得ることができました。やや忙しい1か月間でしたが、とても充実して成長できたと感じています。

## Special Thanks
 今回この企画をご紹介していただいたhataさん（@awonohata）さんにはとても感謝しております。hataさんもご自身のカレンダーで25記事を作成されているので、ぜひそちらもご覧ください。

 https://qiita.com/advent-calendar/2023/hata

 hataさん企画マナビDX Questカレンダー

 https://qiita.com/advent-calendar/2023/manabi-dx-quest2023
Apache Kafkaの使用例

<font color="Grey">*[Use cases for Apache Kafka](https://aiven.io/blog/use-cases-for-apache-kafka)の翻訳です。*</font>

2022年3月20日

# Apache Kafkaの使用例

Apache Kafkaは様々なユースケースに対応できる優れたプラットフォームです。Aivenのお客様がどのようにKafkaを活用し、成果を上げ、複雑さを解決しているかをご覧ください。

ゲーム・ギャンブル事業者[Paf](https://aiven.io/case-studies/aiven-for-apache-kafka-helps-paf)は、機械式スロットマシンを運営する会社から、オフライン施設でも運営しなければならないハイブリッドゲームインフラストラクチャの運営会社に移行しました。


[OVO Energy社](https://aiven.io/case-studies/aiven-for-apache-kafka-helps-ovo)は、Aiven for Apache Kafkaを使用して、エンドユーザーがエネルギー使用量をコントロールできるようにすることで、気候危機に取り組んでいます。OpenSearch、PostgreSQL、Redis、InfluxDB、Grafanaなどと組み合わせることで、Kafkaはデータ収集と分析のギャップを埋める。


[Alef Education](https://aiven.io/case-studies/aiven-for-apache-kafka-helps-alef-education)は、Apache Kafka、InfluxDB、GrafanaのためのAivenで主要な学習プラットフォームを運営している。学習者はオンラインでタスクをこなし、Kafkaはストレージ用のInfluxDBと分析用のGrafanaに情報を渡す。


[GoTo Financial](https://aiven.io/case-studies/goto-financial-goes-far-with-aiven)は、Aiven for Apache Kafkaを介して、巨大なGojekエコシステムに決済やその他の金融サービスを提供している。


[Mirakl](https://aiven.io/case-studies/mirakl-goes-cloud-native-with-aiven)は、オンラインマーケットプレイスの顧客ごとに個別の環境を提供していましたが、Aiven for Apache Kafkaによってマイクロサービス・アーキテクチャに移行しました。


[JobCloud](https://aiven.io/case-studies/building-event-driven-architecture-with-aiven)は、Aiven for Apache Kafkaをレガシーシステムに統合し、現在ではスイス最大の求人サイトを運営しています。新しいセットアップはモダンで、非常に拡張性がありスケーラブルです。


小売業では、[Norauto](https://aiven.io/case-studies/norauto-developers-spin-up-databases-faster-than-ever-with-aiven)がKafkaを使ってPostgreSQL、MySQL、OpenSearch、Redis間でデータを同期し、開発をスピードアップしてデータベース管理のボトルネックを解消している。


また、完全にオンライン化された世界では、[NetSpyGlass](https://aiven.io/case-studies/aiven-cloud-helps-netspyglass) が、AivenのマネージドApache Kafkaを使用して、オンプレミスで自己管理されたネットワーク・モニタリング・オートメーションを近代化し、サービスの範囲を拡大しました。この新しいソリューションにより、同社のエンジニアはネットワークをプロビジョニングするためのより良い、より迅速な方法を開発することができるようになりました。


詳細はこちら[Apache Kafkaとは](https://aiven.io/blog/what-is-apache-kafka)
ChatGPT女子　GP子をデートに誘え！ゲーム

## ChatGPT女子botのGP子ちゃんを無事デートに誘えたらクリア

ChatGPT APIで設定した相手と会話を続けていきます。

gp子ちゃんとLINEでやり取りします。
機嫌を伺いながらタイミングよくデートに誘おう。
上手くデートに誘えたらゲームクリア！
嫌われてしまったりブロックされたらゲームオーバー
やり取りは最大12回まで。

遊んでみてください
https://www.motoblog55.org/invitedate/

 model: "gpt-3.5-turbo"

今回ChatGPTにどんな返事を返してほしいか性格みたいなものを3パターン作り使ってます。
easyモードでは2パターンをランダムで選択します。
デートを承諾するパターンと断るパターンです。

hardモードではネガティブな返事が多くなるように設定。
指定したネガティブワードが出てくると『ブロックされました』となりゲームオーバーになります。

クソアプリ Advent Calendarのためにハードモードを加えました。
年末年始のデートの誘いの練習台にしてみてはいかがでしょうか。
tinkercad.comでLチカしてみた

こんにちわ。ジークスの酒井です。

昔circuit.ioというサイトがあってオンラインで回路を作ってシミュレーションができたんですが
いつのまにか無くなっていて残念だったんですが
別のドメインで復活していたので、また共有してみます

# 準備
tinkercad.comでアカウントを作って新しいプロジェクトを作成します。

# 部品を置いてみる
・「＋Components」を押して、部品を追加する > とりあえずArduino UNO R3とブレットボードを追加してみる 
・LEDと抵抗を追加して、回路をつなげる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160143/4b4c058b-05b2-c87a-7de4-4328160bee37.png)

この図の通りになるように回路をつなげてみてください。
Arduinoの13番、GNDとブレッドボードをつなげます

・コードを編集
「コード」を押した後、ブロックという所を文字に変更してください
そこに以下のプログラムを貼り付けます。
```
int led = 13;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}
```

# Lチカさせる
・準備は出来ました。「シミュレーションを開始」ボタンを押してみましょう！

完成したプロジェクトは以下のリンクからさわれます
はんだ付けとかしなくてもブラウザだけでこんな事できちゃうんですね。
いい時代になりました！

https://www.tinkercad.com/things/0Pvxb1aA7rH-super-tumelo/editel?returnTo=%2Fdashboard&sharecode=FuwfqqA8lipvphwfI8W9BlBQVQfHoqQ3T0AcmA91bio
データで(主成分分析等で)振り返るM-1グランプリ2023


# 1.はじめに

この記事は、NSSOL-アドベントカレンダー2023、2023-12-25担当分です。

https://qiita.com/advent-calendar/2023/nssol

[先駆者の記事](https://qiita.com/haltaro/items/dbfa03c2dd4023316111)を参考に、[M-1グランプリ2023](https://www.m-1gp.com/)の決勝ファーストラウンドのデータを利用して、主成分分析等を行い、理解度を深めます。出場者と審査員の特徴が捉えられたらいいな、と思います。


↓の@haltaro さんの記事では、2017年までのデータにて分析が行われていました。M-1グランプリのルールや主成分分析の理論的背景まで説明されていて、大変分かりやすいです。是非読みましょう。

https://qiita.com/haltaro/items/dbfa03c2dd4023316111

本投稿は、[2023のデータ](https://www.kaggle.com/datasets/gakikame/m1-judge-detail/code)でも同じことをやってみた、という内容です。データ・ソースコード等は↓、のkaggle-Datasetsに置いてあります。

https://www.kaggle.com/datasets/gakikame/m1-judge-detail

関連記事を挙げます。↓は2018-2022年までの記事です。過去との比較用です。

https://qiita.com/gg_hatano/items/3309f485ac666231eb5b

# 2. M1グランプリ2023 
2023年のM1グランプリのファーストラウンドの採点結果を見てみます。

2023年は審査員の入れ替わりがあり、志らくさんが離任し、海原ともこさんが参加しました。

令和ロマン面白かったですね。モグライダーも好きです(ウケが足りないのはなぜ?)。敗者復活のシシガシラのネタも最高でした。トムブラウン、鬼としみちゃむも好きです。エバースも良かった。

# 3. 採点結果
ファーストラウンドの順位で並べています。出典元は[Wikipedia](https://ja.wikipedia.org/wiki/M-1%E3%82%B0%E3%83%A9%E3%83%B3%E3%83%97%E3%83%AA#%E6%B1%BA%E5%8B%9D%E6%88%A6)です。

![スクリーンショット 2023-12-25 6.10.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5897/034a447a-92a5-c548-9aa9-b1f8f8d0a17f.png)

# 4. 過去コンテストとの比較
## 4.1 大会平均点推移
第19回(2023年)の平均点は91.37点でした。2022年は91.99点です。微減です。

![スクリーンショット 2023-12-25 6.16.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5897/8e436387-b446-0e71-f5d9-8b4f9462cce9.png)

レベルの高いトップバッターが基準となり、得点が抑え気味だったのかもしれません。

## 4.2 主成分分析の結果
こんな感じになりました。とりあえず速報です。

左図の右から左が会場ウケの大きさっぽい感じ。左図の下から上は...万人ウケっぽい感じ？
![スクリーンショット 2023-12-25 6.33.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5897/dee449d0-8174-3473-1475-377408850b79.png)


## 4.3 その他の分析結果
いつか気になったら追記します

# 感想
- トムブラウン面白かった
- 登場順が面白かったですね　ジャンル別に出てきた感じ
    - しゃべくり：令和ロマン、シシガシラ、さや香、カベポスター
    - 漫才コント：マユリカ、ヤーレンズ、真空ジェシカ
    - 歌など：ダンビラムーチョ、くらげ、モグライダー

一旦やめさせてもらいます。
競技プログラミングの世界へ挑戦！

## はじめに
　来年やりたいことの一つに競技プログラミングへの挑戦があります。そこで今回は競技プログラミングについて調べてみました。マナビを活かしての今後の展望に乞うご期待ください。

## 競プロのメリット
　まずは競技プログラミングに挑戦したときのメリットを挙げていきます。
- 技術スキルの向上
- 高速のコーディング
- 論理的思考の醸成
- 実績の積み上げ

こんな感じでしょうか

　まず一つ目に挙げたのが、**技術スキルの向上**です。なんといっても競技プログラミングで競われるのはコーディングのスキルではないでしょうか。私も現状のスキルの把握とより上を目指しての成長を求めていきたいです。
 
　二つ目に挙げた**高速のコーディング**ですが、こちらも競技プログラミングで必要なスキルになるのではないでしょうか。競プロで出される課題にはそれぞれ制限時間があるので、いかに素早くコーディングができるかが求められるでしょう。
 　
　ここで挙げたメリット以外に様々な効果を得ることができます。まずはひとまずAtCoderに登録するところから始めていきます。

AtCoder

https://atcoder.jp/

参考


https://chokudai.hatenablog.com/entry/2019/02/11/155904
ポッドキャストのアウトプットを検討してみる

## はじめに
　最適なアウトプットを求めていくつかの記事を書いてきました。アウトプットの一つの案として音声配信を検討してみましょう。

 ## ポッドキャストとは
>ポッドキャストは、インターネットを介して配信されるオーディオ番組の一形態です。一連のオーディオエピソードから構成され、リスナーはこれらをダウンロードして、スマートフォン、コンピューター、タブレットなどのデバイスでいつでも聴くことができます。

## アウトプットの方法として音声配信を選択する理由
　アウトプットの方法として、音声配信を選択する利点として、良いところと言えば説明のスキルが上がることが挙げられます。ブログ記事や動画などと違い文字や画像を一切使えないのが音声です。説明の順番や構成などをしっかり考えて、聞き手に伝わりやすくする必要があります。
 　いくつかのアウトプット方法の中で1番感情が乗りやすいのが、人の声だと考えています。音声データは、その人の話し方、テンポ、感情、を表現することができます。自分の言葉で話すことにより、感情や情熱を直接リスナーに伝えることができます。

　ポッドキャストは、自分自身の考えや情報をアウトプットするための非常に効果的な手段です。自分の声と個性を前面に出すことで、より自信をもって発信することができます。
統計検定準1級を計画する

## はじめに
　今年統計検定2級を取得して、次に目指すものとして準1級の受験を目指していきたいと思っています。そこで今回は準1級の計画をしていこうと思います。

## 2級との違いを把握する
　統計検定2級の受験後、約10か月ほど期間が開いてしまっているのでまずは2級の復習をしたいと思います。ある程度思い出すことができたら、準1級の範囲を理解します。
 
 https://www.toukei-kentei.jp/exam/grade1semi/
 


## Qiitaで参考記事を見つける

https://qiita.com/Ken1234/items/0ac51e21b10568587c95

https://qiita.com/mohki7/items/f4c132ab7098b1767982

https://qiita.com/sflabtech/items/897eb2209a9b0adfeaa1

https://qiita.com/DeepTama/items/9a07129626f82e9add5e


先人の知恵や工夫が凝縮された記事を読んで合格を目指したいと思います。
SSHからCRONの動作確認とリスタートを実行する

## CRONの動作確認
CRONが正常に動作しているかどうかを確認する。
### CRONのサービス状態を確認する
```
sudo systemctl status cron
```
CRONのサービスが実行中であるかどうかを確認できます。"Active: active (running)"と表示されるはずです。もし停止している場合は、以下のコマンドで再起動します。
## CRONのリスタート
以下のコマンドでCRONを再稼働させることができます。
```
sudo systemctl restart cron
```
## CRONのログをチェックする
CRONのログは通常、/var/log/syslog や /var/log/cron に記録されています。
```
tail /var/log/syslog
```
これにより、CRONの実行ログを確認できます。
Drizzle+SQLiteの初歩的な使い方メモ

D1(SQLite)でDrizzleを使いだしてちょこちょこ調べることが必要になった項目のメモ
筆者はSQLiteを使いこんだことがないので、初歩的なことが多いです。

## Schema周り

### AutoIncrement

SQLiteでは列がInteger型かつPrimaryKeyの場合に設定できる。
integerからprimaryKeyを生やし、中にautoIncrementをtrueとすることで設定できる。

```js
	id: integer('id').primaryKey({ autoIncrement: true }),
```

https://orm.drizzle.team/docs/column-types/sqlite#integer

### Boolean

SQLiteにboolean型がないので、整数型を指定し、modeにbooleanを設定します。
結果 0 or 1 で判断するようになります。

```js
import { integer, sqliteTable } from "drizzle-orm/sqlite-core";
const table = sqliteTable('table', {
  id: integer('id', { mode: 'boolean' })
});
```

https://orm.drizzle.team/docs/column-types/sqlite#boolean


### Date型

Booleanと同じく、SQLiteではない型なので、textに保存する。
created_atなど、カラムを追加した日付を入れたい場合は、`default(sql`current_date`)`などを使用する。

```js
const table = sqliteTable("table", {
  time: text("time").default(sql`CURRENT_TIME`),
  date: text("date").default(sql`CURRENT_DATE`),
  timestamp: text("timestamp").default(sql`CURRENT_TIMESTAMP`),
});
```

https://orm.drizzle.team/docs/column-types/sqlite#default-value


## Query周り

### Select

https://orm.drizzle.team/docs/select

#### 全件取得するSELECT

```js
const result = await db.select().from(users);
```

#### 部分的なSELECT

selectにobjectとして渡すことで部分選択ができる。
SQLと同様に、任意の式を使用できる(lowerName)

```js
const result = await db.select({
  field1: users.id,
  lowerName: sql<string>`lower(${users.name})`,
}).from(users);
const { field1, field2 } = result[0];
```
#### 動的条件付きのSELECT

SELECT部分で、三項演算子を利用できる。
下記では、withNameで名前を返すかどうかを選択できる。

```js
async function selectUsers(withName: boolean) {
  return db
    .select({
      id: users.id,
      ...(withName ? { name: users.name } : {}),
    })
    .from(users);
}
```

### WHERE

https://orm.drizzle.team/docs/select#filtering

#### Where

[フィルター演算子](https://orm.drizzle.team/docs/operators)を利用して、クエリをフィルタリングできる。

```js
import { eq, lt, gte, ne } from 'drizzle-orm';
await db.select().from(users).where(eq(users.id, 42));
await db.select().from(users).where(lt(users.id, 42));
await db.select().from(users).where(gte(users.id, 42));
await db.select().from(users).where(ne(users.id, 42));
...
select "id", "name", "age" from "users" where "id" = 42;
select "id", "name", "age" from "users" where "id" < 42;
select "id", "name", "age" from "users" where "id" >= 42;
select "id", "name", "age" from "users" where "id" <> 42;
```

#### WHEREでのAND OR

`and()` `or()`内で、フィルター演算子を組み合わせて、実現できます。

```
import { eq, and, sql } from 'drizzle-orm';

await db.select().from(users).where(
  and(
    eq(users.id, 42),
    eq(users.name, 'Dan')
  )
);
```

その他でよく使うWHERE系のSQLは、直感的に使えるイメージでした。 .orderBy() count("*")など。


### INSERT

https://orm.drizzle.team/docs/insert

#### INSERT時にコンフリクトした場合の処理

`onConflictDoNothing()`をつけることで、重複している場合は、スルーします。

```js
await db.insert(users)
  .values({ id: 1, name: 'John' })
  .onConflictDoNothing();
```

重複した場合に、Upsertする場合は、`onConflictDoUpdate`をつけて、中身にtargetとsetを指定します。

```js
await db.insert(users)
  .values({ id: 1, name: 'Dan' })
  .onConflictDoUpdate({ target: users.id, set: { name: 'John' } });
```
IPv6はIPv4より無条件でセキュアではない理由


オライリーのマスタリングIPsecを読んださい、IPv6が非常にセキュアなのはIPsecを使用しているからだ。というような説明が書いてありました。

しかし、プロフェッショナルIPv6では、それはIPv6は無条件でIPv4よりセキュアなわけではないというような説明が書かれています。

今回はプロフェッショナルIPv6のセキュリティ、特にIPsecの記載内容部分をまとめてみたいと思います。

### RFC7381の記載

RFC7381にて「IPv6はIPv4よりもセキュアというわけではない」と明記されている。

### IPv6の課題

- プロトコルとして新しいということは今後新たなバグが発生する可能性は高い
- セキュリティを確保しながら運用できる経験者が不足している

### IPv6ではIPsecの利用は必須ではない

初期のIPv6の仕様ではIPsecの利用が必須であったが、現在のIPv6ではIPsecは必須ではない。
現在は推奨レベルになっている。
また、必須であったころからずっと、IPv6で行うすべての通信をIPsecで行わなければいけなかったわけではない。

### トンネル技術そのもののリスク

- FWなどのセキュリティ機器が未対応である可能性
- 送信元を偽装する目的に利用可能
- ユーザが張ったトンネルを用いて外部から内部へ攻撃される可能性
- トンネル用のアドレスからプロファイリングされるリスク
- 悪意あるトンネルサーバ設定による中間者攻撃の可能性

本にはありませんでしたが、個人的にはこれらのほかにIPv6アドレスを解決するレコードをDNSサーバに設定する際の人為的なミスなどもリスクかなと思いました。

その他にもIPv6はNATを用いないため、セキュリティリスクが高いなどという意見に対し、NATのあるなしでのセキュリティリスクの増加分は誤差の範囲という反論がRFC4864の中でされていたりもします。

このようなことから、現状一番のリスクは有識者が不足している状態で運用しなくてはならない状態が発生することのような気がしました。
続けること、続けてるとどうにかなること - 2023年のひとりアドベントカレンダー 

## 人生は体力だ

[人生は体力だ - 2023年のひとりアドベントカレンダー #ポエム - Qiita](https://qiita.com/e99h2121/items/09e84075d61d081ec7f5?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share)

そう言って始めました。「言うんじゃなかった…」がネタ的にはお約束ですが、実は意外とわたくしそう思ったことは一度もなく、そもそも「言ってみるもんだな」と思えることを期待して始めています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/cc6d9fff-1456-68d5-d146-65731e059d4a.png)
[エンジニアはどこまで健康になればよいのか - 朝ランと個人的生産性への考察 #健康 - Qiita](https://qiita.com/e99h2121/items/a279f8fb1fbe722aa31f)

続けると良いことは意外といろいろあります。時間が無くて運動できないと思っていたが、運動すると体力がついて稼働時間が増やせることがわかりました。

https://x.com/e99h2121/status/1731093459128418455?s=20


https://www.oreilly.co.jp/books/9784873117287/

[一流エンジニア](https://qiita.com/e99h2121/items/c81071b7d8e7813dd5fd) も続けるからこそだと思います。


## 人のつながりはつづく

2022 年、転職が自分のキャリアの大きな出来事でしたが、2023 年もそれを引き継ぎつつあろうことか前の会社にもお世話になりました。

https://twitter.com/WHI_developers/status/1712747962152145307?s=20

- [発信は良いぞ。「君の会社は 5 年後あるか？」というタイトルで「卒業した会社」にお招きいただいて話した #ポエム - Qiita](https://qiita.com/e99h2121/items/afa2807848e68dc18725)
- [Qiita Advent Calendar 2022 Online Meetup で LT したので、その記録 #Qiita - Qiita](https://qiita.com/e99h2121/items/6857d24a44113bf401b2)
- [日々息をするようにアウトプットしている人は何を意識しているのか？ #ポエム - Qiita](https://qiita.com/satomihoya/items/876dea7dd7a4c90c140a)


一見、自分にとって一銭にもならないことをなぜするのかと思われるかもしれません。が、なんでかなー、を突き詰めた結果こんな感じだなと思いました。

https://x.com/e99h2121/status/1737581572016972036?s=20

結果不思議なことに、色々とお声掛けいただく機会が増えています。

## アドベントカレンダーもつづく

> そんなこんなで体力を維持しながらエンジニア職を続けるために、今年続けてきたこと、続けていること、続けたいことをアドベントカレンダーとして書いていきます。

と初日に書いたはず[^1]  ですが

[^1]:[人生は体力だ - 2023年のひとりアドベントカレンダー #ポエム - Qiita](https://qiita.com/e99h2121/items/09e84075d61d081ec7f5)

以前にその前職で、和田 卓人さんから「量は質を凌駕する」というお話を伺ったことを覚えています。続けるだけで唯一無二になれるというのも一つです。


https://x.com/t_wada/status/824439786672836609?s=20

続けていれば好きなことでお声掛けいただけたりもします。

[「ぼくのかんがえたさいきょうの ERP with Azure Logic Apps」- 第1回 JAZUG for Women で話したので、その記録 #logicapps - Qiita](https://qiita.com/e99h2121/items/d1be586115aaec9d94d0)



## サポートは体力だ… 

[私はサポート職きらいじゃないぞ、という話 #ポエム - Qiita](https://qiita.com/e99h2121/items/e25a4a6990c3997e472b)
[おっさんの小言 令和版 #ポエム - Qiita](https://qiita.com/e99h2121/items/1177d324026f4ad6ebfb)

家のチビッコが小学校に上がったことも含め、充実感あふれる 2023 年でした。2024 年は

- 10 分、15 分で良いから毎日少しづつ読書する
- Logic Apps をさらに布教する
    - [Standard タイプの Logic Apps について少し触れてみる #Azure - Qiita](https://qiita.com/kwtc_/items/afb15b658488502b680e)
    - [Logic Apps をこれから使い始めようという方へ | Japan Azure Integration Support Blog](https://jpazinteg.github.io/blog/LogicApps/LogicApps-HeadFirst/)
- 本を出す
	- [技術系同人誌を書く基礎メモ #Pandoc - Qiita](https://qiita.com/e99h2121/items/72b21cb104f8dee523e0)
	- [技術系同人誌を書く人の味方「Re:VIEW Starter」の紹介 #ReVIEW - Qiita](https://qiita.com/kauplan/items/d01e6e39a05be0b908a1)

結局資格を取っても仕事に慣れても「ポエムを書く人」で覚えてもらえている節があります。以前は何故…という気持ちが大きかったですが、むしろ私の味わいと解釈して。「ポエム」をこれからも書いていこうと思います。

来年も良い年になりますように。素敵なクリスマスと年末年始をお過ごしください。

2024 年につづく！！！
全然よくわかんないけど「phpでも使ってみない？」

# PHPって？
PHPというのは、Webサーバー上で動くプログラミング言語です。
Webサーバー上のリクエストに対して動的にHTMLを生成することができます。

まずは物は試しです。

なお、今回はPHPの環境構築の話は長いのでしません。

# 書いてみよう

```php
<?php
echo "Hello, World";
?>
```

これでアクセスしてみてください。
ちゃんとHello, Worldと表示されたでしょうか。
![スクリーンショット 2023-12-25 050829.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/f6851ea1-3e49-752a-ee17-ae57a96aac4e.png)

phpでは`echo`関数を使用することで、文字列を出力することができます。

# ちょっとした計算をしてみよう

```php
<?php
echo 1 + 1;
?>
```

これでアクセスしてみてください。
なんと、PHPでは計算もできるのです！

...そりゃ、プログラミング言語だからな。

# 変数を使ってみよう

```php
<?php
$var = "Hello, World";
echo $var;
?>
```

phpではこのように`$変数名`とすることで変数を宣言することができます。
また、`echo`関数では変数をそのまま出力することができます。

# 配列を使ってみよう

```php
<?php
$var = array("Hello", "World");
echo $var[0] . ", " . $var[1];
?>
```

phpではこのように`array()`とすることで配列を宣言することができます。
また、配列の要素には`$配列名[インデックス]`とすることでアクセスすることができます。
割とここら辺はそこら辺の言語と同じですね。

# じゃあ応用してPHPをAPIエンドポイントとして使ってみよう

```php
<?php
    if(isset($_GET['username'])){
        $data = array(
            'status' => TRUE,
            'content' => 'Hello, ' . $_GET['username'] . '!',
        );
    } else {
        $data = array(
            'status' => FALSE,
            'content' => 'No Username',
        );
    }
    $jsonData = json_encode($data);

    header('Content-Type: application/json');

    echo $jsonData;
?>
```

まず、`$_GET`というのは、GETリクエストのパラメータを取得するための変数です。
`http://example.com/?username=example`というURLにアクセスした場合、`$_GET['username']`は`example`という値を持ちます。

`isset`では、変数が存在するかどうかを判定することができます。
それをifで判定して、存在する場合は`Hello, {username}!`という文字列を、存在しない場合は`No Username`という文字列を`array`で作成した連想配列に格納します。

また、`json_encode`というのは、配列をJSON形式の文字列に変換する関数です。
これを使うことで、PHPで作成した連想配列をJSON形式の文字列に変換することができます。

最後に、`header`関数を使うことで、レスポンスヘッダーを設定することができます。
今回は`Content-Type`というレスポンスヘッダーに`application/json`という値を設定しています。

そしてそれを`echo`関数で出力することで、APIエンドポイントとして使用することができます。

![スクリーンショット 2023-12-25 052925.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/bd0fb4e4-32fe-2d49-00ff-e39b3d41e4ab.png)

こんな感じで、phpは優秀なAPIエンドポイントとして使うことができます。

# まとめ
といっても私はこの記事を書くにあたって初めてPHPを触ったので、この使い方が正しいのかどうかはわかりません。
まぁでも、PHPはWebサーバー上で動くプログラミング言語なので、APIエンドポイントとして使うのは十分にありだと思います。（ってGH Copilotが言ってます。）

というわけで！！！！
ついに！！！！！！！！！！！！
2023/12/25、5:32をもって、アドベントカレンダー完走です！！！！！！！！！

というわけで、「phpでも使ってみない？」

~~やったああああ！！！！！！~~
~~ついにアドカレ完走して寝れますよ！！~~
~~ほぼオールじゃねぇか！！！~~