OmniAICreator/Qiita-1.07M huggingface dataset:
盗作と呼べる範囲の話

些末ですがこういうものを無断で二次利用するのってどうなんでしょう。
正直そっくりそのまま使うのであれば引用がないと技術者としては報われないし、情報発信をためらう要因になりかねないので引用はちゃんとしてほしいものです。
(ちなみに独創性が欠如して明らかに模倣したものを自己利益目的で発信などしてたら著作権などの侵害もあり得るかなと。作者が申し立てすればの話ですが)

◾️YAML
https://community.sap.com/t5/technology-blogs-by-sap/how-to-use-project-piper-docker-images-for-ci-cd-with-azure-devops/ba-p/13418180

◾️問題の作品
https://qiita.com/tnmrknm/items/d76349a7ae0731b809d3
Emacs Lisp 超初心者がコマンドを作ってみる 〜関数をコマンドにする〜

前回までは関数として実行してきました。

今回はこれまで作ってきた関数をコマンドに化けさせます。

# interactive

関数に (interactive) と書くとコマンドに化けます。本当です信じて下さい。

これで関数はコマンドになります。コマンドになると、皆さんおなじみ M-x で呼び出せたり、キーバインドできるようになります。

````elisp:po-previous-msgid.el
(defcustom po-ediff-previous-msgid-buffer-a-name "*pepm-previous-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)

(defcustom po-ediff-previous-msgid-buffer-b-name "*pepm-now-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)


(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (interactive)
  (po-find-span-of-entry)
  (let (
	(oldbuf (current-buffer))
	(msgid (po-get-msgid))
	(untranslated-regions (po-previous-untranslated-regions))
	)
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-ediff-previous-msgid-buffer-a-name))
      (erase-buffer)
      (dolist (region untranslated-regions)
	(insert-buffer-substring oldbuf (car region) (cdr region))
	)
      (restore-buffer-modified-p nil))
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-ediff-previous-msgid-buffer-b-name))
      (erase-buffer)
      (insert msgid)
      (setq buffer-read-only t))))
````

# 登録

C-M-x

# 実行(呼び出し)

コマンドでは実行方法が関数と変わります。 関数は M-: (eval):(po-ediff-previous-msgid) でしたが、コマンドでは M-x po-ediff-previous-msgid です。

実行結果は前回と変わらないので割愛させていただきます。

今回はここまで。
TSONについて

TSONはTerse Single Object Notationの略です。1つのオブジェクトを簡潔に表現するための表記法です。

# スカラー値
TSONでは値はデフォルトで文字てる型として扱われ、数値型やブール型への変換は暗黙的に行われます。

| TSON文字列 | パース結果     | 
| ---------- | -------------- | 
| foo:bar    | { foo: 'bar' } | 
| foo:false  | { foo: false } | 
| foo:true   | { foo: true }  | 
| foo:5      | { foo: 5 }     | 
| foo:+5     | { foo: 5 }     | 
| foo:-5     | { foo: -5 }    | 
| foo:5.55   | { foo: 5.55 }  | 
| fooo:-5.55 | { foo: -5.55 } | 

空白を含む文字列、数値、ブール値、特殊文字などを定義したい場合はクォートを使います。

```
foo:'true'
```

プロパティを省略した場合は `true` とみなされます。 `foo` というTSONをパースすると、 `{ foo: true }` になります。

空白文字で区切ることで複数のプロパティを持つこともできます。

```
foo:bar baz biz:5
```

# 配列
配列を表現するために、`[]`をつかいます。

```
foo:[5, bar, false]
```

# ネストしたオブジェクト
オブジェクトの中にオブジェクトをいれることもできます。

```
foo:{bar:5 baz:true}}
```

https://github.com/devdigital/tson
VSCodeの背景を好きな画像に！！

# はじめに

この記事は、株式会社スピードリンクジャパン Advent Calendar 2024 の22日目の記事です。
VSCodeのテーマは、開発者の作業環境を快適にするだけでなく、見た目の好みや作業効率にも大きな影響を与えます。今回は背景を好きな画像を表示させる方法をまとめました。

https://qiita.com/advent-calendar/2024/slj

# VSCode拡張機能「background-cover」の使い方
1. 「background-cover」のインストール  
まず、VSCodeの拡張機能マーケットプレイスから「background-cover」をインストールします。

2. VSCodeを開く  
VSCodeを開きます。

3. 拡張機能のインストール  
左側のサイドバーにある拡張機能アイコン（四角形のアイコン）をクリックします。

4. 検索バーに「background-cover」と入力  
検索バーに「background-cover」を入力し、結果から「Background Cover」を選びます。

5. インストール  
「インストール」ボタンをクリックして、拡張機能をインストールします。


# 設定メニューから背景をカスタマイズ
拡張機能をインストールした後、右下のステータスバーに表示される「background-cover」のアイコンをクリックします。これで設定メニューが表示され、以下のオプションを使って背景をカスタマイズできます。
![スクリーンショット 2024-12-19 4.50.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807861/fcd9c245-1ecd-657f-d72b-c580d0946246.png)

1. Select Pictures
Finder or エクスプローラーから背景画像を選択するオプションです。画像を選択すると、その画像が背景として設定されます。
2. Add Directory
背景画像用のフォルダを設定するオプションです。指定したフォルダ内の画像を背景に設定できます。
ランダム選択: フォルダ内の画像をランダムで選ぶオプションです。これにより、VSCode起動時や設定変更時に毎回違った画像が表示されます。
3. Background Opacity
背景画像の透明度を設定できます。0.0（完全に透明）から0.8（完全に不透明）まで調整可能です。
デフォルトは0.2（少し透けて見える程度）になっています。不透明すぎるとコードが見えにくくなるので0.1がおすすめです。
4. Input: Path/HTTPS
画像のパスを直接入力するオプションです。ローカルパスやURLを指定できます。
5. Closing Background
現在表示している背景画像をクリアするオプションです。背景を消したい場合に選択します。
6. On Start Replacement
VSCode起動時に背景画像をランダムに切り替えるかどうかを設定できます。これを有効にすると、VSCode起動時に指定したフォルダからランダムで背景画像が選ばれます。
注意: このオプションは「Add Directory」設定時にのみ使用可能です。

設定すると以下のようになります。
![スクリーンショット 2024-12-19 4.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807861/08246250-9244-5a53-89a2-6381de7380b1.png)



# まとめ
このように、VSCodeの「background-cover」を使用することで、視覚的に魅力的な作業環境を簡単に作成できます。設定メニューから画像を選ぶだけでなく、ランダム選択や透明度の調整、起動時に画像を変更する機能も活用できるので、自分の作業スタイルに合わせて自由にカスタマイズしましょう。
Ubuntu再起動後SSDがアンマウントされ、PythonファイルがPermissionErrorで実行できなくなった人へ

# Ubuntu再起動後SSDがアンマウントされ、Pythonファイルが上手くいかなくなった人へ

---

## 問題の状態

### **発生したエラー**
Ubuntuを再起動後、外付けSSDをマウントしたものの、**Pythonスクリプト**がPermissionErrorで動かなくなりました。

```plaintext
PermissionError: [Errno 13] Permission denied
```

### **状況**
- **OS**: Ubuntu  
- **環境**: スマホからVPN経由でSSH操作中、RebootかけたらSSDがアンマウントされていたので、単純にmountコマンドでマウントし、このSSD内のPythonファイルを実行したところ、このPythonファイルは読み込み、書き込みプログラムを組み込んでいたことから、「書き込み出来ないよっ」というpythonからのパーミッションエラーが発生した。  
- **SSDの状態**: NTFS または ExFATファイルシステム  
- **症状**:  
  - SSDに書き込もうとすると`Permission denied`が出る  
  - ディレクトリの所有者が`root`になっていて、私のユーザー（`masarina`）では書き込めない

再起動する前は普通に動いていたのに…！なぜ…。

---

## 解決までの道のり

1. **マウント状態を確認**  
   マウントポイントの状態がどうなっているのかをチェック。

   ```bash
   mount | grep /media/masarina/AItoKB_mac放
   ```

   → **出力例**:
   ```plaintext
   /dev/sdc1 on /media/masarina/AItoKB_mac放 type exfat (rw,relatime,...)
   ```

2. **掴んでいるプロセスを特定**  
   誰かがこのSSDを掴んでいるのか確認します。

   ```bash
   sudo fuser -m /media/masarina/AItoKB_mac放
   ```

   → 出力例:
   ```plaintext
   /media/masarina/AItoKB_mac放: 2280c 3370c
   ```

3. **掴んでいるプロセスを強制終了**  
   もう遠慮なく終了させる。

   ```bash
   sudo fuser -km /media/masarina/AItoKB_mac放
   ```

4. **強制アンマウント**  
   ちゃんとアンマウントできるか試します。

   ```bash
   sudo umount -f /media/masarina/AItoKB_mac放
   ```

5. **正しい権限で再マウント**  
   ExFAT用のマウントコマンドを使います（NTFSの場合も対応可能）。

   ```bash
   sudo mount -t exfat -o rw,uid=masarina,gid=masarina /dev/sdc1 /media/masarina/AItoKB_mac放
   ```

6. **所有者と権限を設定**  
   自分のユーザーで書き込めるように設定。

   ```bash
   sudo chown -R masarina:masarina /media/masarina/AItoKB_mac放
   sudo chmod -R 755 /media/masarina/AItoKB_mac放
   ```

---

## 最終的な解決策（Bashスクリプト）

同じ手順を毎回やるのは面倒すぎるので、シェルスクリプトにまとめました！  
これを使えば一発で解決できます。

**ファイル名**: `fix_mount.sh`

```bash
#!/bin/bash

# マウントポイントとデバイス
MOUNT_POINT="/media/masarina/AItoKB_mac放"
DEVICE="/dev/sdc1"

# 1. 掴んでいるプロセスを確認して終了
echo ">>> 確認中: マウントポイントを掴んでいるプロセス..."
sudo fuser -m $MOUNT_POINT
if [ $? -eq 0 ]; then
    echo ">>> プロセスを強制終了します..."
    sudo fuser -km $MOUNT_POINT
else
    echo ">>> プロセスはありません。"
fi

# 2. 強制アンマウント
echo ">>> 強制的にアンマウントします..."
sudo umount -f $MOUNT_POINT

# 3. 再マウント（ExFATボリューム用）
echo ">>> 再マウントします..."
sudo mount -t exfat -o rw,uid=masarina,gid=masarina $DEVICE $MOUNT_POINT

# 4. 所有者と権限の設定
echo ">>> 権限と所有者を修正します..."
sudo chown -R masarina:masarina $MOUNT_POINT
sudo chmod -R 755 $MOUNT_POINT

# 5. 状態確認
echo ">>> 最終確認: マウント状態"
mount | grep $MOUNT_POINT
echo ">>> 完了しました！"
```

### **実行手順**
1. スクリプトを保存します。
   ```bash
   nano fix_mount.sh
   ```
   内容を貼り付けて保存（`Ctrl + O` → `Enter` → `Ctrl + X`）。

2. 実行権限を与えます。
   ```bash
   chmod +x fix_mount.sh
   ```

3. スクリプトを実行！
   ```bash
   sudo ./fix_mount.sh
   ```

---

がんばった分、ちゃんとゆっくり休んでねっ！  
**おしまいっ♡**
X-CMDについて


# X-CMD とは

[X-CMD](https://www.x-cmd.com/) とは、ここ数ヶ月で GitHub の Star 数が伸びてきているコマンドプロンプト上で使えるオールインワンツールです
具体的に何ができるのかを細かく説明していきたいですが、できることが多すぎるので簡単なものだけ紹介します

## 1. ネイティブコマンドの強化

デフォルトで存在している linux コマンドである`ls`や`ps`、`cd`、`stat`などのコマンドが機能てんこ盛りになっています
使用例をいくつか挙げてみます
![x-ls.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371529/3e524ebb-e585-09f1-fd09-e65852c46ba2.jpeg)
![x-git.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371529/750e8f07-7123-a69a-a971-e31d148791c8.jpeg)

画像の通り、`x コマンド名`という従来のコマンドとほとんど変わらない使い方でコマンドを使用することができます
`ls` コマンドではエクスプローラーが立ち上がり、探しているファイルへとカーソルを合わせて選択するとそのフォルダに移動するかどうかなどを選ぶことができ、痒い所に手が届くコマンドへと強化されています
このコマンドだと情報量が大きすぎる場合はもちろん、従来の`ls`コマンドを使うことも可能です

また、コマンドプロンプトのテーマに関しても

```bash
x theme
```

とすることで好きなテーマを選ぶことができます
また、どのテーマでも git で管理されているフォルダ内に入ると、現在自分がいるブランチ名がフォルダ名の横に表示されます
これでいちいち`git branch`で現在のブランチ名を確認する必要がなくなります
テーマはデフォルトで 10 種類のパターンと、それぞれのパターンの中でさらに色やフォーマットの小さな違いなどで 20 パターン以上選ぶことができます
たくさんの組み合わせがあるのできっと好みのテーマが見つかると思います

`cat` コマンドも強化されていて、`.java`ファイルなど、拡張子に応じたハイライトが施されるようになっています

## 2. AI とクラウドサービス用の CLI

まだあまり詳しく触れていないのですが、AWS や ChatGPT などの API を CLI から叩けるようです
例：abstract.en.md に書かれた内容を、content.en.md に日本語に翻訳して出力する

```bash
@gpt3 --file ./abstract.en.md　"Translate to japanese" > ./abstract.jp.md
```

また、`x gh repo create`などのように、既存の`gh`コマンドなどが`X-CMD`を導入することにより一括で導入されるようです
とてもではないですが、すべてを紹介し切れる気がしないので気になる人はぜひサイトに飛んで実際に試してみてください

## 3. インストール方法

[公式サイト](https://www.x-cmd.com/)の`install`の方法と、使用している環境に合わせてダウンロード方法を変えてみてください
私は`curl` を使ってインストールしましたが、`wget`でもインストールできるそうです
対応環境は

- Linux
- macOS
- Windows (WSL2 or Git Bash)
  とのことですので、ご自身の環境に合わせて活用してみてください

## 4. 終わりに

今回紹介したのは X-CMD の機能のごく一部です
このアプリは既存のコマンドから使い方をほとんど変化させずに使用感を大きく変えることができるのでコマンドを新しく覚える必要がなく、非常に使いがってた良いなと感じました
まだまだ私の勉強不足で理解できない部分、使いこなせない部分が多くあるので皆さんぜひ自分の手で試してみてください

#### 参考

GitHub リポジトリ：https://github.com/x-cmd/x-cmd
公式サイト：https://www.x-cmd.com/
統計勉強話

## はじめに

Waffleアドベントカレンダー18日を担当します、Waffle college２期生のなほです。
今回はぴよぴよですが大学で統計を勉強している私が今までやってきたことやそれを通じて考えたこと、学んだことを中心にお話しします。
統計に興味ある、やってみたい、今からやる、人にとってはほんのちょっと先を行っている人の話だと思って勉強のモチベーションになったら嬉しいです💖。


## 

統計そしてR（統計で使うプログラミング言語）と出会ったのは大学に入ったばかりの時だったので、なんだかんだ２、３年間のお付き合いがあります。
Waffle collegeでプログラミング言語に初めて触れた〜！と勝手に思っていたのですが、思い返してみるとRが私が一番最初に触れたプログラミング言語だったな、と最近気づきました。　
　
　
転機になったのはゼミ選択です。やっぱりエビデンス（ドヤ顔で言ってみたかった）が重要視されるようになってきた社会の中で、データを使いこなせる人になりてぇぇ〜！という気持ちが芽生えていたので、思い切って社会情報系のゼミを志望しました。その後ゼミに無事合格し専門的な授業をとることも増え、Rや統計、そしてそれに付随して機械学習等もどんどん身近になっていきました。


## 大変なことと学んだこと


そんなこんなで統計の世界に馴染みだした私ですが大変なこともたくさんあります。

 　
まずデータの収集、成型です。分析を始めるにあたってまずは必要なデータを集めて使えるように整えなければいけません。ここでいう整えるとは、霧散しているデータを扱いやすいように一つのファイルまとめたり、いらないデータを削除したりすることを指します。また、欠損している値があるとRで読み込んだ際にエラーが止まらなくて分析にならないという特大インシデントが起きるので注意しなければなりません。
今までは既に綺麗に整った扱いやすいデータを使うことが比較的多かったのですが、もし最初から自力で調査を行って集めるような事になったら本当に本当に大変なんだろうなとつくづく思います。
　
使うことが多いe-Statのデータとデータサイエンス教育のための汎用素材として作成されているデータセット（SSDSE）
高校生、大学生向けにSSDSEを用いたデータコンペティションも毎年開催しているみたいなので興味のある方は是非〜〜

二つとも比較的綺麗で扱いやすいのでおすすめです(✌'ω'✌)(✌'ω'✌)(✌'ω'✌)。

https://www.e-stat.go.jp/

https://www.nstac.go.jp/use/literacy/ssdse/

https://www.nstac.go.jp/statcompe/doing_wp_cron=1734547021.6337571144104003906250

　
また、コードを書いて結果出してはい終わり！！終了！！解散！！で終われるような単純なものではありませんでした。その先の課題解決が目的とされていることも多いので、、、🥺
エラーの対処はもちろんのこと、専門用語の理解だったり、擬似相関（本当は関連しない事象が関連があるように見えてしまうこと）等の気をつけないといけないことがたくさんあったりします。

 　
そりゃ〜〜そうだろうな！！🙃（よく言われているのは人の年齢と年収の推移の話。年齢と年収が比例関係にある）みたいな分析ではなく、自分で立てたテーマや仮説に対してどのようなデータを使って、どのような手法で分析したら有意義な主張ができるかを自分で考えていかなければいけないので、課題設定から分析の流れを考える際には本当に毎回苦労します。ようやく終わりが見えたと思ったらそれ分析の意味あるの？と言われて心が折れたり、結果から見出せた考察が浅すぎてもっとわかることあるよね？と指摘され、自分の考察の甘さと見ていた世界の狭さに絶望したり、、
　
実際今の社会では、一つの事象がそれだけで成立しているのではなくて、様々な事象が複雑に絡み合って成り立っていることがほとんどだと思います。そういった社会に何かアプローチをしたいと考えたときに1つの視点からではなく、その背後にある社会的背景にも目を向け多角的な視点を持つことが重要である、ということにこのような経験を通して気づくことができたので、とても有意義な時間だったと思います。


 　
余談ですが、カフェで友人と作業中にエラーが出たら即帰宅チャレンジを宣言した瞬間、読み込みエラーが起きて即帰宅決定したときがありました。良い思い出です。頼んだピーチティーは８割くらい残っていました。もちろん美味しく頂いて帰りました🍑。


## 最後に

最近はRだけではなく、Pythonで分析ができるように本を見ながら勉強してみたり、未だかつて見たことのない形のグラフを見た目がなんか可愛いからという理由で作ってみたり（動く共起ネットワーク図）、流行ってる分析手法を試してちゃっかり流行りに乗っかった気分を味わったりと楽しみながらゆるくスキルアップを頑張っていますd(:3」∠)_。
　
最近読んでいる本 📚
かなり実践的な内容で、データサイエンティストの仕事のイメージがつかめます。

https://amzn.asia/d/4VkGgSp


 　
気になったことを自分で調べて、データという確実な根拠に基づいて自分の意見が主張できるようになったら本当に最強だと思います。
私もゆるゆると目標に向けて頑張っていくので一緒に頑張りましょう〜(✌'ω'✌)
GitHub ActionsでPrettierによる整形の確認を行った

# GitHub ActionsでPrettierによる整形の確認を行う
## 概要
GitHub ActionsでPrettierによるコード整形の確認を行わせることにした．整形によって自動でコミットが増えるのを避けたいので，整形の自動適用は省略した．Pull Requestごとに整形を確認して，整形漏れがあればテストをfailさせて開発者に知らせる．

## GitHub Actionsとは
[GitHub Actions↗︎](https://github.com/features/actions)とは，GitHub上で，開発工程を自動化するための仕組み．ビルド，テスト，デプロイ，パッケージングなど多様な工程が対象となる．俗にいうCI/CDを実現するための手法の一つ．スクリプトを書いて処理を定義し，その処理をGitHubが用意する計算機上などで実行させることができる．

## Prettierとは
[Prettier↗︎](https://prettier.io/)とは，JavaScriptなどのソースコードやMarkdownなどの文書を，規則に従って整形するプログラム．設定ファイルを共有することで，複数人の共同開発でも書式を揃えることができる．書式を揃えることによって，ソースコードでの意思疎通や差分比較が容易になると期待される．

## 導入方法（Web UI）
1. GitHubのリポジトリページを開き，Actionsタブを開く．
2. New workflowのようなボタン，もしくはCreate your own workflowのようなリンクを押して，入力画面を開く．
3. 次のように入力して，適当な名前で保存する．
  ```yaml
  name: format-checker
  on: pull_request
  jobs:
    format:
      runs-on: ubuntu-24.04
      steps:
        - uses: actions/checkout@v1
          with:
            ref: ${{ github.head_ref }}
        - name: Prettier check
          run: npx prettier --check .
  ```
4. 何かPull Requestを作って，ファイルの整形テストが走ることを確かめる．

## 導入方法（ファイル直書き）
1. `<repository_root>/.github/workflows/<whatever_name>.yaml`に上記内容を書く．
2. Pull Requestを何か作って，動作を試す．

## 動作解説
jobs下に定義されたジョブが自動実行される．
ジョブの一意識別子がformatであり，Ubuntu上でsteps下のスクリプトが順次走る．
最終行の `npx prettier --check .` によって書式整形が済んでいるかを確認する．この時不備があればコマンドが0以外の値を返すので，actionの失敗を検出できる．

## 参考文献
Prettier CIについては[The blog of Peter Evans↗︎](https://peterevans.dev/posts/github-actions-how-to-automate-code-formatting-in-pull-requests/)を大いに参考にした．
GitHub Actionsの基礎的な内容については[GitHub Actions を理解する↗︎](https://docs.github.com/ja/actions/about-github-actions/understanding-github-actions)を参照されたい．
YAMLファイルの構文については[GitHub Actions　のワークフロー構文↗︎](https://docs.github.com/ja/actions/writing-workflows/workflow-syntax-for-github-actions)を参照されたい．
人の視線移動から考える、ボタン内のアイコンは左右どちらに配置すべきか

皆さんはボタンのUIを作成する時、少し戸惑ったことはありませんか？

「戸惑ったことない」という声が非常に聞こえてきそうです...笑

もし作るのがテキストだけのボタンなら、スムーズに作成できるかもしれません。
（もちろん配置するテキストを動詞にするのか名詞にするのかなどの問題はありますが...）

ただ以下の様な「**アイコンを伴ったボタンUI**」だとどうでしょうか？
考えれば考えるほど、あれ、なんでアイコン→テキストの順に配置してるんだろ...ってなりませんか？

![img_button02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/eda911b1-3405-6c1b-9409-f5db64678374.png)
<sub>ZOZOTOWNのiOSアプリから引用</sub>

今回は、ボタンにおけるアイコン位置の疑問を**人の視線移動**という観点から考察してみようと思います。

やや堅苦しい話になるかもしれませんが、興味がある方は是非ご一読いただけると嬉しいです:raised_hand:

## 視線移動と文化的背景
早速初っ端から重めのタイトルですが、アイコンの配置場所には人の視線移動が大きく関わっています。そして視線移動は言語含めた文化的背景と密接につながっています。
なぜなら言語によって、**左右上下の書字方向や読む方向が異なる**からです。

![img_button01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/580e357e-db85-b126-1166-dd35cd990c4d.png)
<sub>iPhoneの言語設定において、2言語の書字方向の違いを示した画像</sub>


**日本語版**と**アラビア語版**で見事に**書字方向が異なり**ます。それに合わせて削除操作の方向も逆になっています。

上記は一例ですが、地域による書字方向とそれに伴う視線移動の違いは、UIデザインにおいても大きな影響を与えます。

### 言語と文化による影響をより詳しく
先ほど取り上げたiPhone言語設定画面のように言語・文化によって以下の特徴があります。

**左から右に読む文化圏**（日本語の横書きや英語）
アイコンはテキストの左側に配置されることが一般的。

**右から左に読む文化圏**（アラビア語など）
アイコンをテキストの右側に配置することで、視線の流れに自然に沿います。

:::note
また先天的に、人間は一般的に左から右への視線移動が優位であり、この特性は読み書きの習慣によってさらに強化されることがわかっています。
:::

## ボタン内のアイコン配置と効果
先ほどまで人の視線移動について考えました。その上でボタン内のアイコン配置をうまく行うと、ユーザーがボタンの機能を素早く理解しやすくなります。

### 左側配置
![img_button03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/8ff6b870-cede-05f4-3231-0286773a0158.jpeg)

テキストの内容を補完するアイコンは、テキストの左側に配置されることが一般的です。言語背景や人間の先天的な特徴により、ユーザーの視線が左から右に自然に流れるため、アイコンを先に認識し、その後にテキストを読むことで直感的に理解しやすくなります。

アイコンは基本的には左に配置すれば問題ないと思います！

### 右側配置
![img_button05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/60b2711f-2e4c-11c2-c2d8-3e1c2c430320.jpeg)

ボタンが進行方向やアクションを示す場合には、アイコンを右側に配置することも考えられます。たとえば、「**次へ**」ボタンでは右向き矢印を右側に配置することで、次のステップへの進行を強調できます。

一方で、アイコンを左側に配置すると「**前へ**」戻るイメージを想起させます。

:::note
右側が「未来」や「次に進む」という概念を連想させる背景には、左から右に読む文化圏特有のメンタルタイムラインがあります。このタイムラインでは、視線の流れが時間の流れ（過去から未来）を表し、右側への視線移動が「次」や「未来」を強調する役割を果たします。
このメンタルタイムラインは、後天的な習慣により強く意識づけられる傾向にあります。
:::

## 結論
今回は、ボタン内のアイコン配置を視線移動の点から考えてきました。
ボタン内のアイコン配置は、視線移動や言語の特徴を考慮することでユーザー体験を向上させるポイントになります。


「人の視線移動」と「ボタン内のアイコン配置」の関係を図解化してみましょう。

![img_button04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/167d1862-264f-0e86-e299-f279190132eb.jpeg)

流れとしては、以下になるかなと思います。
1. 人間は生理的に左から右の視線移動が優位
2. 言語やその他多数の要因によって習慣化
3. 2.により視線移動の流れが決まる
4. 2・3を繰り返すことで視線移動による時間感覚が身に付く
5. 結果ボタン内の適切なアイコン配置

考慮できてない部分は多々あると思いますが、概ね自然な流れかなと思います。

また、上記の1〜5を考慮するとボタン内のアイコン配置は以下のような意味を持ちます。
- **左側配置**: 視線の流れに沿って、内容を補完するアイコンを配置
- **右側配置**: 進行方向や未来を示唆する場合に効果的

視線移動と文化的背景を考慮して、ユーザーが自然で効率的に操作できるUIを提供していきましょう。
本記事を読んで頂きありがとうございました！:bow_tone1:

---

**参考文献**
https://mobbin.com/apps/airbnb-ios-e62cd3cf-0432-4936-903f-b9c01124e2bb/fa759dc1-d52e-4e7f-bc35-0aaf43628e42/flows
https://www.ui-pocket.com/mobile/apps/netflix/2024-11
https://note.com/i3design_design/n/n39fed39dea93
https://pubmed.ncbi.nlm.nih.gov/25495739/
https://osf.io/preprints/psyarxiv/mhaxd
https://pubmed.ncbi.nlm.nih.gov/22201086/
https://www.jstage.jst.go.jp/article/pacjpa/70/0/70_1PM116/_article/-char/ja/
Mitsua_Likes_modelをローカルに保存して実行する

# モデルを保存

1. 下記URLのコードを参考に`mitsua-likes`をgit cloneする  
　[https://huggingface.co/Mitsua/mitsua-likes/tree/main?clone=true](https://huggingface.co/Mitsua/mitsua-likes/tree/main?clone=true)

2. `mitsua-likes`に移動する  
　(例: `cd mitsua-likes`)

3. 仮想環境を作成する 　
　(例: `python3.12 -m venv .venv`)
4. 仮想環境を立ち上げる
　(例: `source .venv/bin/activate`)

5. 下記サイトの手順1～3を実行する  
　[https://note.com/junk_love/n/n0df6e1582860#7e9e0667-39a4-45ae-8bfa-593e4727527f](https://note.com/junk_love/n/n0df6e1582860#7e9e0667-39a4-45ae-8bfa-593e4727527f)

6. 下記コードをPythonファイルに保存して実行する 
　(※　保存するファイルは`mitsua-likes`直下に置く) 
　(例: `python3 save_model.py`)

```
from diffusers import DiffusionPipeline
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16

pipe = DiffusionPipeline.from_pretrained("Mitsua/mitsua-likes", trust_remote_code=True).to(device, dtype=dtype)

# 保存するディレクトリを指定
save_directory = "./mitsua_likes_model"

# モデルをローカルに保存
pipe.save_pretrained(save_directory)
```

# モデルを実行

下記コードをpythonファイルに保存して実行する
　(※　保存するファイルは`mitsua-likes`直下に置く)
　(例　python3 use_model.py)
```
from diffusers import DiffusionPipeline
import torch
import os
from datetime import datetime
from pipeline_likes_base_unet import MitsuaLikesPipeline
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16

# ローカルに保存されたモデルをロード
pipe = MitsuaLikesPipeline.from_pretrained("./mitsua_likes_model").to(device, dtype=dtype)

# 日本語または英語のプロンプト
prompt = "滝の中の絵藍ミツア、先生アート"
# prompt = "elanmitsua in waterfall, sensei art, analog, impressionism painting"
negative_prompt = "elan doodle, lowres"

# モデル推論を実行
ret = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    guidance_scale=5.0,
    guidance_rescale=0.7,
    width=768,
    height=768,
    num_inference_steps=40,
)

# 類似性判定AIの結果を表示
if hasattr(ret, 'detected_public_fictional_characters') and len(ret.detected_public_fictional_characters) > 0:
    print("Similarity Restriction:", ret.detected_public_fictional_characters[0])
    print("Similarity Measure:")
    for k, v in ret.detected_public_fictional_characters_info[0].items():
        print(f"{k} : {v:.3%}")

# 生成された画像を取得
image = ret.images[0]

# 保存先のフォルダを指定
output_dir = "img"
# フォルダが存在しない場合は作成
os.makedirs(output_dir, exist_ok=True)

# 現在の日時を取得してファイル名を作成
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
image_name = f"{current_time}.png"

# フォルダ内に画像を保存
image_path = os.path.join(output_dir, image_name)
image.save(image_path)

print(f"画像が {image_path} に保存されました！")
```

以降も`mitsua-likes`フォルダ直下にいる状態かつ、仮想環境が立ち上がった状態であれば
モデルを実行することが可能です。
SSONについて

SSONはSimple Stupid Object Notationの略でシンプルにオブジェクトを表現することを目的にした表記法です。

# 基本的な構文
SSONの基本的な構文を以下に示します。SSONでオブジェクトを作成するためには、オブジェクト名を書いた行を配置するだけです。一部の単語( `alias`, `default, `.`, `#` )から始まる名前は禁止されていますが、それ以外は自由にオブジェクト名に使えます。
オブジェクトのプロパティを記述するためには、オブジェクト名の次の行に `.` に続いてプロパティ名を配置します。プロパティが空であることを示すためにプロパティを省略します。

```
person
.name = john
.last name = doe
.age = 800

pet
.species = cat
.annoying = very
```

オブジェクト名やプロパティ名に空白を含めることはできますが、両端の空白は自動的に削除されます。そのため、以下のようなスタイルをとることもできます。

```
person
.name      = jane
.last name = doe
.age       = 25

person
.name =   bob
.age =    30
.job =    construction worker
.salary = 123467

  person
. name = bobby
. age  = 60
. job  = who knows?
```

SSONにはコメントもあり、 `#` から始まる行はコメントとして扱われます。行の途中にある `#` はコメント扱いにならない点に注意が必要です。

```
# this is a comment
my object
# this is also a comment
.some property = some value

my other object
.a property = # this is not a comment
# A comment between two properties!
.another property = Hello, World!
```

# デフォルト値
オブジェクトにデフォルト値を持たせることもでき、これを使うことで重複する表記を省略できます。デフォルト値なので、オブジェクトを定義するときに上書きすることもできます。
また、デフォルト値を途中で変更することもできます。


```
default player
.health = 20
.armor = 0
.ammo = 5

# this player will have 20 health, 0 armor and 5 ammo
player
.x = 5
.y = 2

# this player won't have 0 armour because it overrides the property
player
.y = 1
.x = 0
.armor = 10

# it is also possible to change the default values midway
default player
.health = 10

# this player won't have 20 health, but it'll have 0 armor and 5 ammo
player
.x = 6
.y = 12
```

さらに他のデフォルト値を継承しつつ、デフォルト値の一部のプロパティを変更するためにaliasを使うこともできます。

```
default potion
.potency = 5
.price = 10
.name = Potion
.description = A basic remedy

# default poison objects will also inherit the default values of potion as defined above
alias poison potion
.name = Poison
.description = This one doesn't help you get better
```


https://code.dlang.org/packages/simple-stupid-object-notation
【学習物理学入門】1人ゼミやってみた 

# はじめに
こんにちは、九州大学理学部物理学科1年の東山空人です。橋本幸士先生の『学習物理学入門』では、これまでのゼミの根底を覆す、画期的な取り組みが行われています。つまり、1人でゼミができちゃうのです。今回の記事では、この革新的な本（というよりAI？）についてちょっぴり解説しますね。
# 背景
2024年のノーベル物理学賞が、「人工ニューラルネットワークによる機械学習を可能にする基礎的発見と発明」(John J. Hopfield, Geoffrey E. Hinton)に与えられたのは記憶に新しいですよね。僕はYouTubeでリアタイしていて、発表当初、本当にびっくりしました。これは物理なのか…？（愚問）

その後、11月16日に日本物理学会九州支部例会が福岡工業大学で行われまして、学部１年生ながらこれに参加してきました。その際（奇跡的なキャスティングですが）橋本先生の特別講演を拝聴することができました。機械学習は非線形現象を理解するための関数基底（関数近似の手法）のようなもの、宇宙の構造とニューラルネットワークは非常に似ているかも、などなど興味深い話が盛りだくさんでした。帰ってすぐに『学習物理学入門』をAmazonでぽちったのは想像に難くないでしょう。
# How to 1人ゼミ
さて、いよいよ本題ですね。どうやって1人でゼミをするのか？答えはAIとの対話です！この学習物理学入門、**解説用のAIボット**が付属しているのです。著者の1人、三内顕義先生が構築なさったそうです。（すごい）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935905/4c788978-992c-ba9b-2841-e3280401ef6d.png)

例えばこの本の概略を聞いてみると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935905/44d0e054-5ad9-08fc-3954-eb6065048ef8.png)
めちゃめちゃ詳細に教えてくれました。

もちろんこんなこともできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935905/b11a46ed-d635-5d81-cc02-b3fcf2688138.png)
(中略)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935905/4b98f33c-5263-18b4-def3-0feb77f4c476.png)
いわゆる「行間埋め」がAIと一緒にできちゃうわけです。まさに革命。

# 重大な欠陥と結論
しかしながら、1人ゼミ、重大な欠陥を抱えています。AIの問題ではありません、もっと根本的な問題です。（基本的にこいつ、めちゃめちゃ賢いです。）問題は、そう、1人ゼミがとっても**寂しい**ことです。AIの返事に唸ることは多々あります。けれども、やっぱりゼミの醍醐味は、みんなで質問投げかけあって、時に批判して、脱線して、終わった後も学食で議論して…っていうあのワイワイの雰囲気なのです。ですから、AIを**ゼミメンバーの1人**と考えて、たくさんの人間とAIのチームで学ぶのが1番だと思います。そうしないと、AIもなんだか寂しそうじゃありませんか？

というわけで、僕の記事はこれでおしまいです。いかがでしたか？AIと人間の垣根がない世界は、すぐそこまで来ているのかもしれませんよ。（信じるか信じないかはあなた次第）
# 参考文献
学習物理学入門　Introduction to Machine Learning Physics 編：橋本幸士　著：富谷昭夫/橋本幸士/金子隆威/瀧雅人/広野雄士/唐木田亮/三内顕義(2024,11/1) pp17
The Nobel Prize press release (2024,10/8)
https://www.nobelprize.org/prizes/physics/2024/press-release/
ページ上部に設置する横スクロールプログレスバーの作り方

# はじめに
本記事では、ページ上部に横方向に伸びるスクロールプログレスバーを実装していきます。
スクロールプログレスバーを利用する事で、ユーザーに現在の閲覧位置を視覚的に示すことができます。



# ゴール
スクロールすると横方向に伸びるスクロールバーを作成します。

![horizontal-scroll-bar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/9d112304-80f8-52af-dd02-316344615339.gif)



# ソース

- **index.html**

`scroll-progress-bar` と `scroll-progress-fill` の2つの `div` 要素がプログレスバーを構成します。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>スクロールプログレスバーのデモ</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <!-- プログレスバー -->
    <div id="scroll-progress-bar">
        <div id="scroll-progress-fill"></div>
    </div>
    <div class="content">
        <h1>スクロールプログレスバー(横方向) サンプル</h1>
        <p>スクロールすると横方向にバーが進行します。</p>
    </div>
    <script src="index.js"></script>
</body>
</html>
```

- **index.css**

`scroll-progress-bar` は進捗バーの背景部分、`scroll-progress-fill` は進捗を示す水色の部分のスタイルを作成しています。`transition`プロパティに `ease-out` をつけることで、バーの伸縮に緩やかなアニメーションをつけています。


```css:index.css
body {
  height: 2000px;
  text-align: center;
  font-size: 2rem;
  margin: 0;
  padding: 0;
}

/* プログレスバーの背景部分 */
#scroll-progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 20px;
  background-color: #f0f0f0;
  z-index: 1;
}

/* 実際に伸びていく水色の部分 */
#scroll-progress-fill {
  height: 100%;
  width: 0;
  background-color: #0088ff;
  transition: width 0.3s ease-out;
}

.content {
  margin-top: 300px;
}

```

- **index.js**

スクロール位置に基づいてプログレスバーの幅を動的に更新します。スクロール%は、現在のスクロール位置をページ全体の高さで割って算出します。


```javascript:index.js
document.addEventListener('DOMContentLoaded', () => {
    const progressBar = document.getElementById('scroll-progress-fill');

    // スクロール量に応じて進捗バーの幅を更新
    const updateScrollProgress = () => {
        const scrollPx = document.documentElement.scrollTop;
        const winHeightPx = 
            document.documentElement.scrollHeight - 
            document.documentElement.clientHeight;
            
        // 現在のスクロール量を計算
        const scrolled = (scrollPx / winHeightPx) * 100;
        progressBar.style.width = `${scrolled}%`;
    };
    
    // スクロールイベントが発生するたびに、進捗バーを更新
    window.addEventListener('scroll', updateScrollProgress);
    updateScrollProgress();
});
```

# 動作確認

サーバを立ち上げてページをスクロールすると、横方向にプログレスバーが進むことを確認できました。

![horizontal-scroll-bar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/9d112304-80f8-52af-dd02-316344615339.gif)



# 参考

- [MDN Web Docs: Window.scrollY](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY)
- [MDN Web Docs: Element.scrollHeight](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight)
- [CSS-Tricks: Create a Reading Position Indicator](https://css-tricks.com/reading-position-indicator/)
今年モニターが1枚増えました（現在4モニター運用）


[先日投稿した記事](https://qiita.com/tasou-pt/items/bdeadfb5ba057d9823b4)で風景をすこし載せたところ、「キーボードはさておき何枚モニターがあるのよ？」みたいな質問が来たので回答しつつ、そういえば今年モニターを 1 枚増やしたんだったと思い出したので振り返りがてら投稿します。

現在は業務用では**4 枚のモニターに囲まれて**おります。

画面の全体像は下記のとおりです。

![モニターの全体像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/4e5790d9-454c-68dc-71d8-6d6c136578c8.png)

1 つは、バーチャルオフィス系サービスの[metalife](https://metalife.co.jp/)を常時つけております。
今年の 1 月 30 日くらいにふと気づき、家にあった Raspberry Pi 用の小型モニターを付けた次第です。

それで 4 モニター運用となりました。

![IMG_0489.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/d6f8d95b-9031-ceee-1465-e280a5806f91.jpeg)

まあ、追加したモニターは、両面テープで貼ったうえでクランプで挟んで固定している感じです。
なかなかに無茶なことをしております。

また余談ですが[metalife](https://metalife.co.jp/)は、軽い会話の風景も外から感じられたり、結構ほどよい距離感でリモートワークができるのでいいサービスだと思います。

![会話しているところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/c52aeed3-fc9b-2101-c1b1-57927fe59c1f.png)

話していると吹き出しが出てくるので離れていてもなにかやっているのかが分かります。

簡単な離席だったら取り込み中（相手から話しかけられなくなるモード）の設定にしつつ、コメントも入れておけば具体的に取り込み中な理由もわかって配慮しやすいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/33d7309b-4ea7-28f3-d69e-9df9926ec8f1.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/ea1b6719-dcd1-b462-9ffd-91f28ebfedf1.png)

私も急に話しかけられることはあるのですが、その時に他の業務中だったりしてウィンドウを探すようなことをするくらいなら、モニターにずっと表示しておけば丸く収まるぞというコンセプトです。

他の 3 ウィンドウは、優先順位の高い打ち合わせを表示するモニターや、複数の web の打ち合わせに参加するときなどにそれぞれのウィンドウで別な打ち合わせをする、といったことも出来るようになります。

ちなみにそんなときも、設定情報にある「音量ミキサー」の項目で、あまり聞く必要のない会議は音声のボリュームを下げたりして対応します。音の機器分けのためにも、音量を変更できるようになってるといいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553291/a09e90bb-6fc9-7908-c88c-cfa2fe8e121c.png)

業務効率を見つめ直すのも楽しいです。
モニターのEDIDを取得したい

## EDIDとは
https://e-words.jp/w/EDID.html
## 経緯
Elgato 4K60 proを買った
↓
4k CaptureUtilityを起動しないとパススルー出力されない
↓
キャプボにはカスタムしたEDIDを読ませて別のモニターとして認識させれる
↓
出力したいモニターのEDIDを取得してカスタムEDIDを作成する

## 取得方法
1\. モニターのプロパティ>詳細>デバイスインスタンスパスを確認
2\. レジストリエディタで`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\[デバイスインスタンスパス(DISPLAY\以降)]\Device Parameters`をコピー
3\. コマンドプロンプトで以下のコマンドを実行すると出力される
```bat
reg query [取得したレジストリのパス] /v 'EDID'
```
【VSCode おすすめ機能】InlayHintを活用してコードを快適に書こう 【TypeScript・JavaScript】

# はじめに
今回は、VSCodeのおすすめ機能、InlayHintについて紹介していこうと思います。

## InlayHintとは
みてもらった方が早いので、以下の画像をご覧ください。

![スクリーンショット 2024-12-19 0.42.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/6022de28-3fa5-2763-e9a6-46828b30fe75.png)

これはjsのファイルですが、変数や関数の引数に薄灰色で型情報などが表示されています。

このように、インラインでレンダリングされるソースコードに関する追加情報のことをInlayHintといいます。

https://code.visualstudio.com/Docs/editor/editingevolved#_inlay-hints

これが表示されていると、関数の引数の順番を間違えることが少なくなったり、変数に意図しない型が入ってしまっているのが視覚的に検知できて助かることがままありますので設定することをお勧めします！

後述しますが、邪魔だという方は特定のキーを押している間だけ表示することもできますので、設定するだけしておいても良いと思います！

## 使い方
VScodeの設定で`inlayHints`と検索し、以下の項目にチェックをつけます。
項目ごとにサンプル画像を貼ってくれているので、必要だと思う項目を選びましょう。

- `JavaScript › Inlay Hints › Enum Member Values`
- `JavaScript › Inlay Hints › Function Like Return Types`
- `JavaScript › Inlay Hints › Parameter Names`

- `JavaScript › Inlay Hints › Parameter Names(Suppress When Type Matches Name)`
- `JavaScript › Inlay Hints › Parameter Types`
- `JavaScript › Inlay Hints › Variable Types`

TypeScriptを使用している場合は以下もチェックをつけます。
- `TypeScript › Inlay Hints › Enum Member Values`
- `TypeScript › Inlay Hints › Function Like Return Types`
- `TypeScript › Inlay Hints › Parameter Names`
    - これはSelect形式なので`all`を指定
- `TypeScript › Inlay Hints › Parameter Names`
- `TypeScript › Inlay Hints › Parameter Types`
- `TypeScript › Inlay Hints › Variable Types`
- `TypeScript › Inlay Hints › Variable Types(Suppress When Type Matches Name)`

これでts,jsファイルに戻ると、薄灰色の表示がされているはずです！

もし、表示されていない時は`editor.inlayHints.enabled`がONになっているか確認してみてください。

## 特定のキーを押している間だけ表示する

前述した、特定のキーを押している間だけ表示する方法についても紹介します。

VSCodeの設定で、`editor.inlayHints.enabled`を検索します。

`Editor › Inlay Hints: Enabled`という項目が出てきますので、Selectで`offUnlessPressed`を選択します。

![スクリーンショット 2024-12-19 1.42.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/20f389fd-0351-3acf-5a60-6d9a5ad3cc83.png)

こうすることで、普段は表示せず、`Ctrl+Option`を押している間だけInlayHintsを表示することができます！

## おわりに

最後までお読みいただきありがとうございました！

こういった設定で、コーディングにかける時間を少しずつでも減らして効率を上げていきたいですね！
position stickyでHTML要素を画面にとどまらせる

## HTML要素を画面に張り付かせる
小さなダイアログやヘッダー、広告といった、スクロールをしても画面の特定の位置に表示しておきたい要素がでてくることがあります。

JavaScript による実装で位置を固定しておくことも可能ですが、CSSの`position: sticky`を利用すると、要素を画面の特定の位置に表示しておく粘着動作を簡潔に実現することが可能です。

## `position: sticky`
`position: sticky`は要素を粘着させるCSSプロパティです。
スクロールを行った際に、要素を特定の箇所にとどまらせることができます。

`position: sticky`によって、粘着をさせるには、`top`や`bottom`、`left`や`right`といった、いわゆる`inset`プロパティも一緒に指定する必要があります。
`inset`プロパティが1つも指定されていない時には、`position: relative`として扱われ、粘着動作は起こらなくなります。

### 粘着先の要素の決まり方
`position:sticky`が指定された要素は、その祖先要素のうち`overflow: visible`(デフォルト値)以外の値をもつ最も近いものに粘着します。
そのため、画面全体のスクロールに粘着させるには、各祖先要素が`overflow: visible`を持たないことが必要になります。

`overflow-x: scroll`や`overflow-x:hidden`など、横軸への指定であってもその祖先要素へ粘着することとなる点には注意が必要です。

https://developer.mozilla.org/ja/docs/Web/CSS/position

## JavaScript での実装
`position: sticky`は、祖先要素の`overflow`プロパティによっては画面全体に粘着させられないため、祖先要素の`overflow`プロパティを変更したくない場合には別の方法で粘着動作を実現する必要が出てきます。

スクロールに応じて要素の位置を変更する方法の一つとして、JavaScriptで`scroll`イベントを監視し、位置を更新する方法があります。
`getClientBoundingRect`[^1]や`document.body.scrollTop`などを使用して位置を計算し、要素の`style`属性を使って位置を指定して実現します。

しかし、`getClientBoundingRect`を使用すると、ページ上の要素の正確な位置とサイズを計算する必要があるため、強制リフロー[^2]が発生する点には注意が必要です。

強制リフローによるパフォーマンスの低下を回避するには、デバウンスやスロットリングによって頻度を落とす方法のほか、`Intersection Observer`API を利用する方法もあります。

`Intersection Observer`はスクロールなどのイベントではなく、要素が画面に表示されているかを監視できるため、スクロールイベントを監視するよりもパフォーマンスの点で優れます。

https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API

[^1]: [`getClientBoundingRect`](https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect)は、ビューポートの上端から要素の上端までの距離やビューポートの左端から要素の右端までの距離を返す`Element`のメソッドです。
[^2]: ブラウザが要素の位置やサイズを再計算し、画面上のレイアウトを即座に再構成すること。Forced Synchronous Layout とも呼ばれます。ブラウザの通常の最適化サイクルを中断して強制的に行われるためパフォーマンスに悪影響をあたえます。
ソースコードの品質担保を自動化する技術

:::note info
本記事は[アジアクエスト - Qiita Advent Calender 2024](https://qiita.com/advent-calendar/2024/asiaquest)の記事です。
:::

# はじめに

ソフトウェアの内部品質は開発生産性に大きく関わってきます。
内部品質の中でも保守性が低いと、可読性が原因でソースコードの解読が難しくなったり、設計の複雑さが原因で新機能の追加やバグ修正が難しくなってしまいます。
全てではないですが、ソフトウェアの内部品質は静的解析ツールや自動テストなどを使ってある程度担保することができます。

本稿では、自動化の重要性と自動化環境を構築するスキルがなぜ重要かを考えていきます。
最後に、Node.js環境を例に具体的に自動化環境に必要なツールを紹介します。

## 自動化しないとどうなるのか

静的解析ツールや自動テストを導入したものの、これらの実行を自動化しないとプロジェクトに悪い影響がでる可能性があります。
ソースコードの変更をコミットする前に手動で確認するよう、個々人の開発者に求めてしまうのは非効率です。
こういった面倒はできるだけ自動化して、開発に集中できるような環境を整えることが重要です。

ソースコードを自動でチェックする環境が構築されずにプロジェクトが進んでしまうと、ソースコードがカオスな状態になってしまう可能性があります。
主に、次のような問題が発生すると考えられます。

- 開発者間でコードの書き方に差異が生まれてしまい可読性が落ちてしまう
- いざビルドしようと思ったときに、コンパイルが通らなくなってしまう
- この前まで成功していた自動テストが失敗してしまう

いずれも、ソフトウェアや開発者にとっては良くない出来事です。
これらの問題は、すべて自動化によって解決可能だと思います。

## 自動化すると何が嬉しいのか

自動化のデメリットはなんとなく理解できましたが、逆にメリットは何でしょうか。
具体的には、次のような恩恵を受益することができます。

- バグを早期に発見できる
- ソフトウェアの品質をある程度担保できる
- 自動化により手作業が減り、開発者はより開発に集中できる

## 自動化するスキルがチーム開発にもたらす恩恵

自動化するスキルは、チーム開発において良い恩恵をもたすと考えています。
私が勝手に尊敬しているプログラマであるtwadaさんは自動化することの重要性について次のように述べています。

> 自動化っていうのは一度やれば、何度でも自動で動いて早期に受益できます。
> チーム開発の場合誰か一人が自動化すれば全員が受益者になれます。
> これはとても大きいことですね。
>
> [t-wadaさんが後世に残したい、実録レガシーコード改善](https://www.youtube.com/watch?v=WQRU_BJaVoU)

これは「一人が皆のため」や「自己犠牲」のような綺麗事ではなく、一人が頑張ってしまえば他の人はノーコストで恩恵を受けられるということです。
このことから、自動化をするスキルを持っていることはチーム開発においてコーストパフォーマンスが高く有益なスキルだと言えるでしょう。

# Node.js環境で自動化するにはどうすればいいか

まずは、何をどのタイミングで実行するかを考える必要があります。

よくあるケースとしては、メインブランチにコミットをマージするときにCIを実行するというケースがあります。
CIを実行するケースでは、ソースコード管理をGithubで行っている場合は、Github Actionsを使ってCIを実行することが可能です。
その他にも、AWS CodePipelineやCircleCIなどのサービスを使ってCIを実行することもできます。

https://docs.github.com/ja/actions/about-github-actions/about-continuous-integration-with-github-actions

https://aws.amazon.com/jp/devops/continuous-integration/

また、ローカルのコーディング作業でコミットしたときにも自動化を行うことができます。
Node.jsのプロジェクトであれば、HuskyとLint-stagedを使って、コミット時に静的解析ツールや自動テストを実行することができます。

https://typicode.github.io/husky/

https://github.com/lint-staged/lint-staged

手段がきまったら次は、何を自動で実行するかを考える必要があります。

## 静的解析ツールを導入する

静的解析ツールは、ソースコードのコーディングスタイルをチェックするツールです。
よく使われる静的解析ツールはESLintで、最近ではBiomeも人気があります。
設定はできるだけ厳しくすることで、コードの品質を高く保つことができます。

https://eslint.org/

https://biomejs.dev/ja/

## 自動テストを導入する

JestやVitestなどのテスティングフレームワークを導入することで、自動テストを行うことができます。
自動テストの導入は比較的コストがかかるため、まずは誰か一人がお手本になるテストを1つだけでも書いてみると良いでしょう。

https://jestjs.io/ja/

https://vitest.dev/

## ビルドを自動化する

ビルドを自動化することで、いつでもデプロイ可能な状態を保つことができます。
なので、できるだけビルドを自動化することをおすすめします。

TypeScriptを使っている場合、tscコマンドを使ってビルドすることができます。
Viteやesbuildなどのビルドツールを使っている場合は、ビルドコマンドを実行すると良いでしょう。

https://ja.vite.dev/

https://esbuild.github.io/

# 参考資料

https://speakerdeck.com/twada/working-with-legacy-code-the-true-record

https://www.youtube.com/watch?v=WQRU_BJaVoU

https://aws.amazon.com/jp/devops/continuous-integration/

https://about.gitlab.com/ja-jp/topics/ci-cd/benefits-continuous-integration/
新卒一年目が考える、情報系専門学校を卒業してためになったこと3選

## はじめに
はじめまして！情報系専門学校を卒業し、新卒でIT企業に勤務して8か月の者です！
**「専門学校に通うか迷っている」** **「実際に通っているけど、この経験は本当に役立つのだろうか」** そんな不安を感じている方も多いのではないでしょうか？

私自身も在学中の経験が、将来どれだけ役に立つのか分からず、迷うことがたくさんありました。しかし実際に働き始めてみると、**「あの時の経験があったからこそ今がある！」** と思う瞬間が何度もありました。

この記事では、専門学校を卒業してIT業界に飛び込んだ私が **「これは本当にためになった！」** と感じた3つのポイントを具体的なエピソードを交えながらお伝えします。

専門学校への進学を迷っている方、あるいは在学中の方の不安を少しでも解消し、前向きな気持ちになってもらえたら嬉しいです！

### プロフィール
* 三年制専門学校を卒業
* 在学中は認定資格の取得やチームでのアプリ開発を経験
* 毎日約8時間のアルバイト生活（103万の壁完全破壊）
* 現在はインフラエンジニアとして勤務
* 最近ボーナスでスノーボードを購入！

# 結論
専門学校で得られた学びの中で、私が特に役に立ったと感じているのは以下の3点です。

**1. チーム開発を通じてプロジェクトの流れを理解したこと**

**2. 資格取得でITの基礎知識と自信を身につけたこと**

**3. 問題に直面した際の向き合い方を学んだこと**

この記事では、それぞれのポイントについて私自身の経験をもとに、社会人になってからどのように役立ったのかを具体的にご説明します。

## チーム開発を通じてプロジェクトの流れを理解したこと
一つ目は **「チーム開発を通じてプロジェクトの流れを理解できた」** 経験についてお話します。私が通っていた専門学校では、チームでアプリを開発する中で、プロジェクトの進行方法を学ぶことができました。

例えば、現実の社会問題を解決するアプリを企画するところから、基本設計書やクラス定義書を作成し、レビューを受けるといったプロセスを経験しました。また、WBSを作成して進捗管理を行ったり、Gitを活用してコードの管理を行ったりと、実務を意識した開発を体験することができました。

…といった話だけ聞くと順調に進んだよう思われるかもしれませんが、実際は**試行錯誤の連続**でした。初期の頃は、Gitを使わずGoogle Driveでファイルを共有したり、設計書の修正を何度も繰り返したり、さらにはWBSを大幅に超過して毎日のように居残り作業をしていたこともあります（笑）。

それでも、3年間で4回のチーム開発を経験したことで、効率的な開発方法やプロジェクトの流れを徐々に理解できるようになりました。
その結果、実際に配属された案件でも、「なぜこのタスクが必要なのか」を考える癖がつき、業務を深く理解できるようになりました。（まだわからないことばかりですが…！）

こうした専門学校でのチーム開発を通じて経験した失敗や苦労が、現在の私の**土台**となっています。

これが学生時代チーム開発で **「失敗」して「ためになったこと」** 1つ目です。

## 資格取得でITの基礎知識と自信を身につけたこと
二つ目は、**「資格取得を通してITの基礎知識と自信を身につけることができた」** 経験についてお話します。私が通っていた専門学校では、資格取得を強く推奨しており、資格別に特化した授業を受けることができました。その結果、手厚いサポートのおかげもあり、在学中に多数の資格を取得することができました。

資格取得の経験は、現在の私のIT基礎力と自信の源となっています。資格の勉強を通じて新たな知識を得る楽しさや、合格したときの達成感を何度も味わいました。しかしある時、資格取得そのものが目標になってしまい、ITの知識を身に付けるという**本来の目的を見失っている**ことに気づきました。

**資格はあくまでも、ITの知識をインプットするための手段の一つであり、取得することがゴールではありません。** この自身の目的と価値観のズレに気づき、自分の学びの方向性を見直すことができたのも、資格取得に集中できる環境を提供してくれた専門学校のおかげです。

社会人となった今でも、エンジニアとして日々新しい知識を学び続けています。資格取得はその一環として役立っており、学び続ける習慣を持つことで、成長し続けることができています。

これが、学生時代に多数の資格取得を **「実践」して得られた「ためになったこと」** の２つ目です。

## 問題に直面した際の向き合い方を学んだこと
三つ目は、**「問題が起きた時の向き合い方を身につけた」** 経験についてお話しします。

専門学校時代、何かを開発したり行動したりするたびに、大なり小なり問題が発生することを身をもって経験しました。例えば、チーム開発ではタスクの遅延やメンバー間の意見の食い違い、コードの不具合など、数多くの課題に直面しました。

特に印象に残っているのは、アプリ開発のプロジェクトで発生したバグを全員で解決した時のことです。最初は何が原因か全く分からず、時間だけが過ぎていきました。しかし、一つひとつ原因を洗い出し、時には全く面識のない講師や先輩に相談しながら問題に立ち向かい、最終的にバグを修正することができました。この経験から、問題解決には **「焦らず、冷静に状況を分析すること」「一人で抱え込まず、周囲の力を借りること」** が重要であると学びました。

また、問題に直面するたびに **「どうしてこの問題が起きたのか？」「次に同じ問題を防ぐためには何をすべきか？」** といった振り返りを行う癖が身につきました。
こうした習慣は社会人になった今でも活きています。現在の業務でも、失敗した際には同じように原因を追求し、解決策や再発防止策を考えることができています。
それが必ずしも解決や再発防止に繋がるわけではない未熟者ですが、問題に対する向き合い方を学ぶことができたのは、**失敗を恐れず挑戦する場を提供してくれた**専門学校のおかげだと感じています。

これが学生時代に　**「問題」と向き合い、「ためになったこと」**　の3つ目の要素です。

## 締めの言葉
これらの学びを得ることができたのは、ただ受け身で講義や課題に取り組むのではなく、**「どうしたらもっと良い成果が出せるのか」「なぜこの作業を行うのか」** と常に考え、主体的に行動してきたからだと思っています。専門学校という環境は、努力する人にとって無限の可能性を広げられる場所です。

だからこそ、これから専門学校に入ろうか迷っている方や、在学中の専門学生の皆さんには、**自分の手で未来を切り開く行動力** を持ってほしいです。最初は不安や迷いもあるかもしれませんが、まずは一歩踏み出して挑戦を重ねることで、必ず自分の成長を実感できる瞬間が訪れます。

この記事が、少しでも皆さんの背中を押すきっかけになれば嬉しいです。そして、あなた自身の努力によって作り上げる未来を、心から応援しています！
Postman テンプレート ライブラリを使おう！

こんにちは！ 福岡でエンジニアをしているはっしーです！

普段はC#、.NET、Azureなどの技術を使ってWebアプリケーションを開発しています。
バックエンド寄りです！


今回は、新規でPostmanのWebAPIのコレクション、リクエストを作成するときにPostmanのテンプレートライブラリが便利だったので紹介します！

## はじめに
みなさんは自身で開発しているWebAPIをテストする際、どんな流れでPostmanを使用していますか？

このような流れが多いのではないでしょうか？

- ワークスペースで新しいコレクションを作成する
- コレクションにリクエストを追加する
- 対象のAPIにリクエストを送るためにHTTPメソッド、エンドポイント、ヘッダーなどを設定する

CRUD操作を行うREST APIだったら、HTTPメソッドごとにリクエストを作らないとですね。
- GET
- POST
- PATCH
- DELETE

あとは使いやすいようにBaseURLなどの変数の設定を行ったりしますよね。

並べてみると簡単だけど少し手間ですよね...

## Postmanのテンプレートライブラリ

Postmanには、WebAPIのワークフローを開始するためのフレームワークを提供する無料でカスタム可能なテンプレートがあります。
https://www.postman.com/templates/

テンプレートには、バックエンドエンジニア、フロントエンドエンジニア、フルスタックエンジニア、QAエンジニアなどの役割に応じたものがあります。

また、プロトタイピング、ドキュメンテーション、テスト、デモなので特定のユースケースのためのテンプレートもあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/df0e9259-0e7d-ae07-6618-c076b2777f06.png)

テンプレートを使うことでWebAPIをテストをさくっと開始することができます。


## テンプレートを見てみよう

### REST API basics テンプレート

- テンプレートを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/e7f608e3-6aef-0d1a-dfe9-44c4645e437a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/7113f38d-890f-8839-44b8-a5c04d0cb272.png)

- ワークスペースを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/6f017389-b762-ac44-8ea9-9898508e4597.png)


#### テンプレートの中身

CRUD用のリクエストがあります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/b61d18ed-44bb-026c-5257-d7a1b74a52cc.png)

ちなみにPostmanはこちらの右上のボタンを押すと、使用されている変数を一覧で確認することができます
変数を確認すると`BaseURL`が設定されてます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/0daf4ec2-11d0-c6a5-2503-a6280e204156.png)

あとはレスポンスのステータスをテストするためのスクリプトも記述されてます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/32fd3367-e27d-ffc2-9e01-f73d3658e278.png)

シンプルな構成ですね。テンプレートをベースにCRUD 操作 (GET、POST、PUT、DELETE)、変数、およびテストを含むリクエストをさくっと作成することができますね

### Integration testing basics テンプレート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/8deb924b-3645-a0c3-37fb-13900ef8a710.png)
- テンプレートには登録、登録したユーザー名の取得、登録解除の3つのリクエストが含まれています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/01ae501a-f124-335d-d8eb-32d053ee275e.png)
- 実行ボタンを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/16d36c02-e379-16fe-001d-2a303237b5ce.png)
- 「Run Integration testing basics」を押すと、3つのエンドポイントを使用した統合テストを行うことができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/2287ba3d-67d7-dd91-3e99-5f96855f2b67.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704555/925c96f5-4efe-44c9-39ae-fd31a1325e76.png)

こちらのテンプレートをベースにするとWebAPIの統合テストをさくっと作成することができますね

## まとめ
テンプレートを使用した方が断然早くWebAPIのテストを行うことができます。
最近はもっぱらテンプレートを使用して始めているのでおすすめです。

また、統合テストやE2Eテストなど初めのうちは1から記述するのは大変なワークフローもテンプレートを使用すると書きやすいです。

是非WebAPIのテストを始める際はテンプレートを使用してみてください。


最後まで読んでいただきありがとうございました。
レガシーコードを触れて学んだこと/ What I learned from touching legacy code (日本語 / 英語)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/8ef84ae2-9c44-4df8-8c4c-ce18037dca08.png)
# 日本語
こんばんわ！
Advent Calendar 2024に参加してまして、18日目の記事を書いていこうと思います。
題材は「レガシーを保守したり、刷新したりするにあたり得られた知見・ノウハウ・苦労話 by Works Human Intelligence Advent Calendar 2024」ということで、過去のバグ改修をした際の苦労話をしていこうと思います。

### レガシーコードとは
レガシーコードとは、もはや開発が進んでいない、あるいは他の開発者によって書かれた古いコードのことを指します。こうしたコードに手を加えるのは時に恐ろしい仕事に感じることもありますが、上手にアプローチすることで効率的に問題を解決することができます。私が担当したレガシーコードのバグ改修は、特定の機能が予期しない挙動を示し、ユーザーからのフィードバックを受けて修正が求められたケースでした。

### レガシーコードに触れて学んだこと

###### ドキュメントとテストの重要性:

レガシーコードにおいて最も大きな問題は、ドキュメントやテストコードが欠けていることです。これらを整備しておくことで、将来的な修正が格段に楽になります。

###### 慎重かつ段階的なアプローチ

レガシーコードの改修は慎重に進めるべきです。一度に多くの変更を加えるのではなく、段階的に進め、テストを確実に行いながら進行することが重要です。

###### コードの可読性と保守性の向上

ただバグを修正するだけでなく、コード全体の可読性や保守性を向上させる意識が必要です。これが後々の作業を効率化します。

ここまで読んでいただきありがとうございます！
# ENGLISH
Good evening!
I'm participating in Advent Calendar 2024, and I'm going to write an article for the 18th day.
The subject is “Knowledge, know-how, and difficulties gained in maintaining and renewing legacy code by Works Human Intelligence Advent Calendar 2024,” and I would like to talk about some of the difficulties I had in fixing bugs in the past.

### What is legacy code?
Legacy code is old code that is no longer under development or has been written by other developers. Working on such code can sometimes feel like a horrible job, but a good approach can solve the problem efficiently. A bug fix I worked on for legacy code was a case where a particular feature exhibited unexpected behavior and required a fix based on user feedback.

### What I learned from working with legacy code

###### the importance of documentation and testing:.

The biggest problem with legacy code is the lack of documentation and test code. Having these in place will make future modifications much easier.

###### A Cautious, Step-by-Step Approach

Modifications to legacy code should be approached carefully. Instead of making many changes at once, it is important to proceed in stages and ensure that testing is performed as you go.

###### Improving Code Readability and Maintainability

In addition to just fixing bugs, there must be an awareness of improving the readability and maintainability of the code as a whole. This will make your work more efficient later on.

Thank you for reading this far!
AWSアカウントの閉鎖にあたって知っておくとよいこと

こんにちは。
突然ですがAWSアカウントを閉鎖したことはありますか？私はもあります。
閉鎖にあたって知っておくとよいことをまとめてみます！

## 実際の閉鎖は90日後
アカウントを閉鎖してから90日間は、アカウントを再開することができます。
再開する場合はAWSサポートに連絡すればOKです。逆に90日を超えると一切再開できなくなるので注意しましょう。

## 閉鎖ができるのはrootユーザのみ（スタンドアロン環境）
スタンドアロン環境においてAWSアカウントを閉鎖できるのはrootユーザのみです。IAMユーザ/ロールでは閉鎖はできません。rootユーザでアカウントにログインできない状態の場合、まずはログインできるよう認証情報の再設定が必要となります。再設定が必要になってしまった場合、登録時のメールアドレスや電話番号を利用できないと困ったことになる可能性があるので連絡先が変わったら忘れず更新するようにしましょう。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reset-root-password.html

https://aws.amazon.com/jp/premiumsupport/knowledge-center/reset-mfa-device1/

なお、Organizations環境下のメンバーアカウントであればrootユーザでなくても閉鎖が可能です。

https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_accounts_close.html

## メールアドレスは再利用不可
閉鎖したAWSアカウントが利用していたメールアドレスを使って、AWSアカウントを新規作成することはできません。必要な場合はメールアドレスを閉鎖前に変えましょう。

https://docs.aws.amazon.com/ja_jp/accounts/latest/reference/manage-acct-update-root-user.html

## ハードウェアTOTPを解除する
閉鎖したAWSアカウントでハードウェアTOTPを使用していた場合、同じハードウェアTOTPを別のAWSアカウントで使用することはできません。あらかじめ解除しておきましょう。なお、現在ではハードウェアTOTPよりFIDO2のセキュリティキーのほうがAWSにより推奨されている点は頭の片隅に入れておくとよいと思います。

> 物理的な MFA デバイスを使用する場合は、ハードウェア TOTP デバイスの代わりに FIDO セキュリティキーを使用することをお勧めします。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/enable-mfa-for-root.html#hardware-totp-token-for-root

## Savings Plans/RIは引き続き課金
AWSアカウントを閉鎖したとしても、購入済みのSavings Plans, RIについては引き続き課金が発生します。期限が残っているRIをAWSの利用者間で売買するReserved Instance Market Placeは日本人にとっては敷居が高い（米国の住所が必要）です。アカウントの閉鎖が見込まれる場合にはRI/SPの購入は控えましょう。

## マーケットプレイスの解約を忘れずに
アカウントを閉鎖したとしても、AWSマーケットプレイスのサブスクリプションは勝手に解除されません。継続的に課金が発生するのでマーケットプレイスの解約をアカウントの閉鎖の前に行いましょう。

https://docs.aws.amazon.com/ja_jp/marketplace/latest/buyerguide/cancel-subscription.html

## ログ/証跡を保全する
CloudTrailやConfig Snapshotなどの証跡を自アカウントのバケットに保存している場合、アカウントの閉鎖に伴って消えてしまいます。他のアカウントのバケットに退避しましょう。

なお、マルチアカウント環境においてはログ/証跡保存用の専用のAWSアカウントを用意するのがベストプラクティスになっています。マルチアカウントの場合は検討するとよいでしょう。なおこの場合証跡をKMSで暗号化していると、アカウント閉鎖後にログを読めなくなるのでその点は注意が必要です。

https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/encrypting-cloudtrail-log-files-with-aws-kms.html

## データを退避する
アカウント閉鎖後は当然アカウント内に保存されているユーザのデータにはアクセスできません。必要なデータは退避しましょう。

# おわりに
アカウントを閉鎖にあたって知っておくとよいことをまとめました。
何かのお役に立てば幸いです。
Clojure: DuctでRSSリーダーを作る - DB接続(HikariCP, Jdbc)

![advent_calendar_2024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/f4cd8ce0-6352-a1d8-4cae-f39dd44f4def.png)

[*Advent Calendar 2024 Day 21*](https://qiita.com/advent-calendar/2024/clojure)

昨日は`Duct`でルーティングを実装しました

今日はDB接続したいと思います。

:::note warn
今回の記事ではpostgresqlに接続しますが、
DBの立ち上げ部分に関しては省略します
:::

データベース接続を作るのに、`HikariCP`というものを使おうと思います

## DB接続プール

`HikariCP`は高速かつ効率的なデータベース接続プールライブラリです。

さっそく`project.clj`に追加します

```clojure:project.clj
  :dependencies [[org.clojure/clojure "1.10.3"]
                 [duct/core "0.8.0"]
                 [metosin/ring-http-response "0.9.4"]
                 [duct/module.ataraxy "0.3.0"]
                 [duct/module.logging "0.5.0"]
                 [duct/module.web "0.7.4"]
                 [duct/database.sql.hikaricp "0.4.0"] ; 追加
                 [org.postgresql/postgresql "42.7.4"] ; 追加
                 [com.github.seancorfield/next.jdbc "1.3.981"] ; 追加]
```

ついでに`postgresql`ドライバーと、`jdbc`というデータベースアクセスライブラリを入れました

次に`config.edn`に設定を追加していきます

```clojure:config.edn
  :duct.database.sql/hikaricp
  {:adapter "postgresql"
   :server-name "localhost"
   :port-number "5432"
   :username "user"
   :password "password"
   :database-name "feed"}

  :clojure-rss-reader.handler.feeds/get
  {:db #ig/ref :duct.database.sql/hikaricp}
```

ここでは、DB接続情報を`:duct.database.sql/hikaricp`に設定しています。

そしてその設定情報をhandlerに渡しています。

`#ig/ref`はIntegrantの依存関係の参照を表していて、`:db`に渡しています

## データ取得

次に、ハンドラー側の実装をいじっていきます

```clojure:handler/feeds.clj
(ns clojure-rss-reader.handler.feeds
  (:require [ataraxy.response :as response]
            [integrant.core :as ig]
            [next.jdbc :as jdbc]
            [next.jdbc.result-set :as rs]))

(defn get-feeds [db]
  (let [result (jdbc/execute! db ["SELECT * FROM feed"] {:builder-fn rs/as-unqualified-lower-maps})]
    {:feeds result}))

(defmethod ig/init-key ::get [_ {{:keys [spec]} :db}]
  (fn [_]
    [::response/ok (get-feeds spec)]))
```

こんな感じで実装しました

`db`を受け取りデータベースの値を返す`get-feeds`という関数を作り、それをhandlerで呼び出しています

実際にリクエストを送ってみましょう

まずサーバーを起動します

```bash
$ lein repl
user=> (dev)
:loaded
dev=> (go)
:duct.server.http.jetty/starting-server {:port 3000}
:initiated
```

そしてリクエストを送ってみます

:::note info
解説はしていませんが、postgresqlをローカルに立てています。
:::

```bash
$ curl localhost:3000/v1/feeds | jq .

{
  "feeds": [
    {
      "id": 1,
      "url": "https://www.google.com",
      "title": "Google",
      "description": "Googleのトップページです。",
      "created_at": "2024-12-19T05:24:36Z"
    },
    {
      "id": 2,
      "url": "https://www.yahoo.co.jp",
      "title": "Yahoo! JAPAN",
      "description": "Yahoo! JAPANのトップページです。",
      "created_at": "2024-12-19T05:24:36Z"
    }
  ]
}
```

いい感じでDBに入っているデータを取得することができました。