OmniAICreator/Qiita-1.07M huggingface dataset:
【PowerDNS,BIND他】 DNSロードバランサーのDNSDistを触ってみる　～その２～

## 前回からの流れ
DNSクエリのロードバランシングソフトウェアであるPowerDNS dnsdistを通した形での名前解決を確認しました。今回は、一般的なDNSサーバ環境に近い構成とした上でdnsdistのクエリ処理状況を確認するダッシュボードの設定と簡単なブロック動作を確認していきます。

 * PowerDNS DNSdist
   * https://www.powerdns.com/powerdns-dnsdist
 * DNSdist documentation
   * https://dnsdist.org/index.html
## 実行環境、構成
 * OS：WSL2 Ubuntu 22.04
 * dnsdist：1.8.2-1
 * powerdns：4.5.3-1

![dnsdist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/f1e371c1-c11c-860d-ac69-02b761458a5d.png)

### 前回実行環境からのdnsdist.conf変更点
WSL2上にコンテンツDNSサーバを配置したため、以下の通り変更しています。
```shell
変更前：newServer({address="172.26.0.1:53", name="dns1", qps=300})
変更後：newServer({address="172.26.2.3:15053", name="dns1", qps=300})
```

### 検証用コンテンツDNSサーバの設定
下記レコードを含むexample.comゾーンを用意
```shell
www          IN      A      192.168.5.1
srv          IN      A      192.168.5.2
*            IN      A      192.168.5.123
```
## dnsdistのダッシュボード設定
dnsdistでのクエリルーティング動作状況を確認可とするため、ダッシュボード設定を追加します

 * dnsdist.confへダッシュボード用設定を追加します。
```shell。
# vi /etc/dnsdist/dnsdist.conf

-- dnsdistのダッシュボード設定
-- https://dnsdist.org/guides/webserver.html
webserver("172.26.2.3:8083")
setWebserverConfig({password="supersecretpassword", apiKey="supersecretAPIkey", acl="172.26.0.0/16"})

※注意…検証のため、ダッシュボードのbindポート/パスワード/APIKEYをデフォルトとしています。
```
 * 設定反映のため、dnsdistをrestartします。
```shell
# systemctl restart dnsdist
```
 * ダッシュボードURLへアクセスすると、以下画面が表示されます。
   * ユーザ名：任意
   * パスワード： setWebserverConfigのpassword値
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/ebdb35d5-8c85-5d3c-6f9b-0c0b63e846ca.png)

## 特定DNSレコードのブロック用ルールを追加
検証用レコードであるsrv.exmaple.comの名前解決を行わないよう、dnsdistにて対象クエリをdropさせる単純なルールを追加します。

* dnsdist.confへブロック用ルールを追加します。
```shell
# dig -p 10053 @172.26.2.3 srv.example.com +norec +short
192.168.5.2
# vi /etc/dnsdist/dnsdist.conf
-- 特定DNSクエリのブロック
-- https://dnsdist.org/rules-actions.html
addAction("srv.example.com.", DropAction())
```
* 設定反映のため、dnsdistをrestartします。
* digコマンドにて、正しくDNSクエリがブロックされる事を確認します。
```shell
# dig -p 10053 @172.26.2.3 srv.example.com +norec +short
;; communications error to 172.26.2.3#10053: timed out
;; communications error to 172.26.2.3#10053: timed out
;; communications error to 172.26.2.3#10053: timed out
```
* また、追加したダッシュボード上からブロック状況を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/fb524177-3db8-cb1c-c813-36befd414b6c.png)

## おわりに
今回の記事では、dnsdistのダッシュボード設定の追加および特定レコードの簡単なブロック設定を追加しdnsdistの動作を確認しました。次回は、今回に引き続きクエリルーティングの設定とダイナミックルールに関する動作を確認していきます。
[Tips] Instana Agentを複数のバックエンドに接続する

[Instana Observability Advent Calendar](https://qiita.com/advent-calendar/2023/instana) をご覧の皆様、おはようございます。こんにちは。こんばんは。
23日目の記事です。週末なのでサクッと読める内容にしたいと思います。

私は業務において自身の検証環境へInstana AgentをインストールしてInstanaの機能を色々検証することがあるのですが、その際に時々使う小ワザ（？）をご紹介します。

普段はとある検証用のバンクエンドへ、自身の検証用サーバーに導入したInstana Agentを接続しています。が、この検証用バックエンドが何らかの理由で一時的に利用できない場合や、個別プロジェクトでの検証を行う場合に、一時的にInstana Agentを異なるバックエンドにも接続したいケースがあります。そんな時に使っている方法です。

Instana Agentは複数のバックエンドに接続させることが可能となっています。その方法は[製品マニュアル "Configuring Multiple Backends"](https://www.ibm.com/docs/en/instana-observability/current?topic=agents-configuring-host#configuring-multiple-backends) で紹介されています。これを使います。

設定は簡単です。
例えば Instana Agent を2つのバックエンドに接続させたい場合、"Instana Agentディレクトリー"/etc/instana にある com.instana.agent.main.sender.Backend.cfg ファイルを コピーして、次のように2つのファイルを用意します。

```
com.instana.agent.main.sender.Backend-1.cfg
com.instana.agent.main.sender.Backend-2.cfg 
```

コピー元の com.instana.agent.main.sender.Backend.cfg はリネームしておきます。
（残っていると新たに作成した2つのファイルが読み込まれません。）

そしてそれぞれのファイルに記述されている次のパラメーターを、それぞれ接続させたいバックエンドのものへ変更し、保存します。いずれの値もそれぞれのバックエンドの「Instana Agentのインストール」画面で確認できます。

|パラメーター名 |設定内容|
|---|---|
|INSTANA_AGENT_ENDPOINT|バックエンドのAgent接続用エンドポイント|
|INSTANA_AGENT_ENDPOINT_PORT|バックエンドのAgent接続用エンドポイント・ポート|
|INSTANA_AGENT_KEY|Agent接続用のキー|

Instana Agentを再起動します。

これでInstana Agentは2つのファイルに記述されたバックエンドへ接続します。

以上です。
明日はクリスマス・イブですね。
それでは皆様良い週末を！
インストールしても損は無しVSCode拡張機能

そもそも1つの記事にするほど、沢山入れてない。。
最低限として、インストールしても損はないでしょう！

まずは
|拡張機能|概要|
|----|----|
|Japanese Language Pack|日本語|
|SQLite|SQLを簡単に見える化|
|Auto Rename Tag|HTML終了タグ自動補完|
|Code Spell Checker|ソースコードのスペルミスチェック|
|indent-rainbow|ソースコードのインデントに色が付く|
|Prettier Code formatter|ソースコード自動整形|
|zenkaku|全角スペース可視化|
|Django|Django使うなら必須
|Python|Python使うなら必須
|Pylance|Python用エラーチェック
|isort|Python用importの順番
|Jupyter|Jupyter使うなら必須
|Jupyter Cell Tags|Jupyter用
|Jupyter Slide Show|Jupyter用

使い方や、初期設定はその都度検索しましょう！
用途に合わせた設定をして、使いましょう！
現在でも新しくgdriveをlinuxで動かす方法【2023/12/16成功】

# Tl;DR(12/19追記)

https://github.com/glotlabs/gdrive

を使ってください。指示に従えばちゃんと動きました。
以上。

# 旧 TL;DR

・https://github.com/BugCode1/gdrive/releases/tag/2.1.2 から対応するバージョンのURLをコピー

自分のバージョンは`uname -m`とかで見られます

・URLを自分にあったバージョンに書き換えて、ターミナルで以下を順番に実行
(以下はLinux x86_64での例)
```bash:bash
wget https://github.com/BugCode1/gdrive/releases/download/2.1.2/gdrive_2.1.2_linux_amd64.tar.gz
```
```bash:bash
tar xvf gdrive_2.1.2_linux_amd64.tar.gz
```
```bash:bash
mv gdrive /usr/local/bin/
```

また、Replitなどのsudo権限がない環境では、3つめは実行せず、パスを指定して実行するか、自分でパスを通しているところにおいてあげてください。

例：同じディレクトリにgdriveのバイナリがある場合
```bash:bash
./gdrive list
```

実行出来たら、出力されたリンクに任意のブラウザでアクセスし、ログインしたいアカウントを選択してください。
そうすると、
`http://localhost:1/?state=state&code=******&scope=https://www.googleapis.com/auth/drive`
みたいなURLに飛ばされるので、******の部分をターミナルに打てば完了です。

# きっかけ
https://github.com/prasmussen/gdrive/tree/2.1.1

gdriveという、LinuxからGoogleDriveを操作できる便利なライブラリがあります。
しかし、この更新がかなり止まっており、現在ではError 400: というエラーになってしまいます。

そこでissueを読み漁っていたところ、上記の解決方法を発見しました。

gdriveの使い方はたくさんあるのでここでは割愛します。

お役に立てば幸いです。

参考(翻訳元):
https://github.com/prasmussen/gdrive/issues/663#issuecomment-1357293108
AWS資格（SAA-C03）合格までのステップ

この記事は [AWS Advent Calendar 2023](https://qiita.com/advent-calendar/2023/aws) 23 日目の記事です。
## はじめに
業務でAWSに関わっているため、せっかくなのでAWS資格であるSAA-C03（AWS Certified Solutions Architect - Associate）を取得しようと思い立ちました。
結果は767/1000点（720点ボーダー）でギリギリでした…

## 試験内容
### 難易度
中級。AzureでいうとAZ-104と同じくらいのレベルと思っています。
### 構成
65問、140分です。

## 受験方法
以下のAWS公式サイトの「試験のスケジュールを立てる」をクリックすると「AWS認定アカウント」のマイページに飛べますのでそこから試験を予約できます。
ページを進んでいくと、途中からピアソンVUEのページに飛んでそこからテストセンターなどを決めます。オンライン受験も可のようです。
https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/

ちなみに、合否結果は試験会場ではわからず、上記のページからわかります（結果が出ると「試験履歴」ページの「受験履歴」に表示されます）。
私の場合は朝11時半頃に試験が終わり、当日19時頃に結果が出ていました。

## 試験形式
4択の選択問題のみになります。

## 勉強方法
### とりあえずAWSを触る
業務でAWSを基盤としたシステム設計の検討に関わっていたので、前提となる知識は事前にある程度身についていました。
そんな中意識した点としては**実際にAWSを触る**ことです。それは、試験に受かるだけの勉強ではなく資格取得後も身になる勉強をしたうえで試験に合格したいからです。

具体的には以下のようなことをする中で、知識を蓄えていきました。
・AWSコンソールに入ってEC2を作成し、Web3層システムを構築（VPC周りやEC2に強くなる）
・cloudformationを使って上記の環境を再構築
・ビジネスプランに申し込んで（月額最低$100）Guard DutyやSecurity Hubなどを有効化してみる
・System managerで自分だけの監視ダッシュボードを作ってみる

### 網羅的に理解できる本を読む
以下の本も読破しました。AWS全体の知識が網羅的かつ体系的に頭に入りました。
「AWS認定資格 ソリューションアーキテクトアソシエイトの教科書: 合格へ導く虎の巻」
https://www.amazon.co.jp/dp/B0BCPNZ9GJ?tag=nokonokonoko0-22&linkCode=ogi&th=1&psc=1
Amazon prime会員であったため、私が閲覧した時点でKindleにて読み放題の本でした。

### 模擬問題で試験対策
Udemyの「【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）」の模擬問題を仕事のスキマ時間でひたすら反復しました。セールの時に購入したので2000円くらいだったと思います。
https://www.udemy.com/course/aws-knan/
AZ-104を取った時にUdemyの問題集が解説が丁寧でわかりやすかったので今回も利用しました。実際、本番では65問中10問くらいは、ほぼ同じか似たような問題が出題されたと思います。
この問題集はかなり難しい問題が掲載されていると感じました。私の場合、知識が身についてきた終盤でも初見の問題を解くと正解率が20%くらいでした。
なんとか模擬問題の1,2,3,5を全て90%以上とるまで繰り返し、最後の方は問題文を少し見るだけで回答がわかるくらいになっていました（4は時間的に間に合いませんでした）。

### 最後にPing-t
最後にチョコっとPing-tの無料問題を実施しました。こちらも解説が丁寧でわかりやすかったです。
https://mondai.ping-t.com/g
ですが、例えばEC2とはどのようなサービスですか？のような、本番と比べて簡単な問題が多い印象を受けました。本番ではそのようなシンプルな問題は出題されず、要件を紐解いてそれを実現するための設定値もしくは機能、サービスを答える必要があります。

## 注意事項等
・試験中、前の問題に戻ることができるので後で見直しが可能です。
・最後の問題のページで次へを押すと見直し用に全ての問題に飛べるリンクページがでます。私はそれを知らずに最後まで解き終えてから65回前へを連打して見直しをしていました…
・解答の選択肢から先に読むと問題文が頭に入りやすいです。

## おわりに
Udemyの問題集を解いているときは受かる気がしないと思っていましたが、頑張って解き続けてよかったです。
個人的な転職失敗談

## 転職について

今までIT系としては2社経験してます。
1社はITベンチャーで、もう一つはITベンダーです。

技術力不足に起因した人間関係での失敗が多いような気がします。

結局のところ、「事前に準備しておく」「たくさん行動する」「壁にぶつかったときに早急に対応する」しかないと思います。

## ケース１（ITベンチャー）
#### 入社前
開発メンバーのリーダーが積極的に会話してくれる
環境よいことをおしえてもらい、安心した状態で入社

#### 入社後
良くも悪くも制度的にちゃんと決まっていない部分が多く、自由度が高い
メンバー間でサポートしあうというよりは個々人で自分で進んでいくスタイルが重視されている
内部での課題が山積、リーダーはその対応に追われているためこちら側へのサポートは比較的少ない

#### 社内の開発チーム環境
- 開発のリーダーは、自由に動くスタイル
- デザイナーがいない、デザインは各々で考えて調整する
    - デザインがまとまらないと問題が生じる、時間がかかる
- アジャイル的な開発プロセスだが、社内でオリジナルな調整方法を取る
- 若手メンバーしかいない
    - ある程度年数がいくと皆どこかへ去っていく

#### やれたこと
- ある程度の技術理解
- ある程度の社内の雰囲気づくり

#### 失敗まとめ
- 社内変化に対応できなかった
    - 特に情報共有や報告なく状況が変わっていくので、情報の取捨選択をしながら前に進む必要があった
- 勉強量の不足
    - 他メンバーが凄い勉強していたので、相対的に少なくなってしまった
    - 他メンバーよりも多くする必要がある。。。
- 社内でのイニシアティブがとれなかった
    - 根回しや関係構築をそこまでやっていなかった
    - 価値観の相違から衝突することが嫌になってしまった
    - 自分から発言していく、声を出していく必要があった
- 業務を獲得できなかった
    - 業務の取り合いをする気が起きなかった
- 自分の幅を自分で狭めてしまった（デメリットを考えすぎてしまった）
    - インフラ周りなどやったことない業務を敬遠してしまった
    - 周りにもっと話しかけて質問して知識を増やせばよかった

## ケース２（ITベンダー）
#### 入社前
- いいプロジェクトが多いことを聞く
- 環境面で自分にあっていると感じる
#### 入社後
- 希望したプロジェクトに入ることがかなり困難、自由度は低い
- 若手が多い、ほとんどが数年で皆転職していくため社内の人間関係は深まらない
- プロジェクトに入れていない人が多い
- 社内のメンバーの能力にかなりの差がある、配属部署に経験者が少ない

#### プロジェクト環境
- アジャイル開発だが、そこまで厳密にはしていない
- 複数のPMメンバーが主体的に開発をリード、バックグラウンドが異なるので意見がぶつかる
- 開発メンバーは優しいが、腹の内は分からない
- 開発リーダーは要求レベルが高そう
- こちらのリーダーは技術初心者レベル、ウォーターフォール派
- こちらのベテランメンバーはあまり参加できない

#### 課題に感じたこと
- SIerてきな価値観とWeb系の価値観がぶつかってうまくいかない
    - どこまでコードを作りこむか
    - 開発で何を重要視するか
- ウォーターフォールとアジャイルでぶつかってうまくいかない
    - ウォーターフォール派はアジャイルを嫌う場合がある
        - タスクが増えてしまうと思っている？
- こちら側のリーダーがGitHubなどの開発環境に否定的、開発リーダーと衝突
    - 自分から丁寧に説明すればよかったかもしれない


#### やれたこと
- ある程度の他社メンバーとのコミュニケーション

#### 失敗まとめ
- プロジェクトでのイニシアティブがとれなかった
- 上のメンバーをフォローしすぎた
- もっと幅広いメンバーとコミュニケーションすればよかった
    - PMの求めるコミュニケーション能力はかなり高め
    - いろいろな人の意見を聞かないと何がプロジェクト内で正しいか分からない

## 今後にできること

- イニシアティブの取り方を研究する
    - 初動を早くして、アーリーサクセスを取りに行く必要がありそう
- 基本的に周りにいる全メンバーと会話できるように動く
    - 八方美人てきに動く必要がある、批判が出ないようにうまくバランスを取っていく
- 自分は何でどう貢献するかを考える
    - 強みを明確にする、対応を早くして素早く行動して結果を出す
    - 参画して初期の段階は、ほかのメンバーよりも動いて汗をかくことで信頼を勝ち取るしかない。。。
- 業務を獲得する
    - 上司や周りに遠慮しない
    - 積極性をアピールしていく



## 総じて
- <b>覚悟を持って入社して、何事にも柔軟に我慢強く対応、本当に厳しかったら他の道を探る</b>
    - 入社前に言われたことと実際の業務内容が異なることが多い
        - 入社前に言われたサポート体制などは実際にはなかったりする
            - 基本的には「自分でなんとかして」というパターンが多い
        - 社内の状況でどうにでもなってしまう危険性を考慮しておく必要がある
    - 入社前は社内の雰囲気などやはりどうしてもいいように言われるし、こちら側もいいように受け取ってしまう
    - 主体性や積極性がかなり求められる、入社前にそういったことを共有されない
クロージャーコンパイラーでJavaScriptを圧縮する

![DALL·E 2023-12-16 11.56.30 - A hacker using Closure Compiler, depicted in a modern, technology-driven setting. The hacker is intensely focused on multiple computer screens, displa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/b6ab2e4f-d3c0-122d-1d65-f18c19263aff.png)

# はじめに

クロージャーコンパイラーってご存知ですか？
JavaScriptの最適化ツールで、JavaScriptのコードを圧縮し、実行速度を向上させるための効率化を行なってくれます。

ChatGPTにも聞いてみますかね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/3482bebb-607e-6632-5834-a8ae69421c9a.png)

```互換性を向上```させることもできるんですね。:memo:

# 導入

久しぶりに使ってみようと思い、オンラインツールにアクセスしてみると、

https://developers.google.com/closure/compiler/docs/gettingstarted_ui?hl=ja

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/72786b66-a81f-5d7e-39f5-7b082c39089f.png)

なんと、サポート終了となっています。

別の方法を探してみると、npmモジュールとしてGoogle様から提供されていることがわかりました。
自分のPCで実行できるので、コンパイルされたコードのコピペが不要になり、便利ですね。

導入方法は簡単です。
配布元のページがシンプルにわかりやすいです。

https://www.npmjs.com/package/google-closure-compiler

npmコマンドを使って、google-closure-compilerを導入します。
```shells
npm install --save google-closure-compiler
```

はい、終わりました。

# 使い方

使い方も簡単です。
配布元のページがシンプルにわかりやすいです。

```shells
npx google-closure-compiler --js=my_program.js --js_output_file=out.js
```

(補足)
my_program.js: 圧縮したいJavaScript
out.js: 圧縮されたJavaScript

はい、終了です。

# 終わりに

当記事は、[こちらのQiita](https://qiita.com/karamaki/items/5cbb84c0ddd3e2cc3fe5)の「方法３：Bookmarkletにする」に触発されました。

ブックマークに登録するJavaScritコードの生成にも使用できます。

# 参考

https://developers.google.com/closure/compiler/docs/gettingstarted_ui?hl=ja

https://www.npmjs.com/package/google-closure-compiler

https://qiita.com/karamaki/items/5cbb84c0ddd3e2cc3fe5
Laravel SailをPHP 8.3でインストールする

別の記事を書く目的で新しいLaravelプロジェクトをインストールしようとしたときに、どうせならPHP 8.3を使ってみようと思ったものの、環境構築で一瞬悩んだので備忘録。

# 新規Laravelプロジェクトダウンロード & インストール

公式ドキュメントの通りインストールしてみます。

```sh
curl -s https://laravel.build/php83-laravel | bash
```

https://laravel.com/docs/10.x/installation#sail-on-windows

たちあげてバージョンを確認してみると・・・8.2ですね。

```sh
# Laravelのプロジェクトディレクトリに移動
cd php83-laravel

# コンテナ立ち上げ
./vendor/bin/sail up -d

# コンテナ名確認
docker ps 
CONTAINER ID   IMAGE                         COMMAND                  CREATED         STATUS                            PORTS                                                                                    NAMES
934dda75ba0a   sail-8.2/app                  "start-container"        6 seconds ago   Up 4 seconds                      0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:5173->5173/tcp, :::5173->5173/tcp, 8000/tcp   example-app-laravel.test-1

# バージョン確認
docker exec -it php83-laravel-laravel.test-1 php -v
PHP 8.2.13 (cli) (built: Nov 24 2023 08:47:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.13, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.13, Copyright (c), by Zend Technologies
    with Xdebug v3.3.0, Copyright (c) 2002-2023, by Derick Rethans
```

# ドキュメントを再確認
再度確認してみると、Getting Startedのページとは別のページに記載がありました(~~そばに書いておいてほしい~~)。
`docker-compose.yml`ファイルをいじりなさいということですね。

> The default PHP version used by Sail is currently PHP 8.2. To change the PHP version that is used to serve your application, you should update the build definition of the laravel.test container in your application's docker-compose.yml file:

https://laravel.com/docs/10.x/sail#sail-php-versions

# docker-compose.ymlを編集する
ドキュメントの指示に従って、該当する部分を変更します。

```yml
    laravel.test:
        build:
            # context: ./vendor/laravel/sail/runtimes/8.2 
            context: ./vendor/laravel/sail/runtimes/8.3 # ここを変更
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        # image: sail-8.2/app
        image: sail-8.3/app // ここも変更
```

# 再ビルドして立ち上げ

無事PHP8.3でアプリケーションコンテナが立ち上がっていました。

```sh
# ビルドと立ち上げ
$ ./vendor/bin/sail build --no-cache && ./vendor/bin/sail up -d

# バージョン確認
$ docker exec -it example-app-laravel.test-1 php -v

PHP 8.3.0 (cli) (built: Nov 24 2023 08:50:08) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.0, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.0, Copyright (c), by Zend Technologies
    with Xdebug v3.3.0, Copyright (c) 2002-2023, by Derick Rethans
```

# 実際にビルドファイルの構成を見に行ってみる
無事動いたものの、せっかくなので構成を見に行ってみましょう。
対象のディレクトリを探しに行くと、`8.2`以外にも`8.0` ~ `8.3`までディレクトリがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533643/df9c3d86-8f1a-b3b3-ffb5-d89a3380c4dc.png)

Laravel Sailのパッケージの一部として複数のPHPバージョンの設定ファイルを同梱しておくことで、PHPのバージョン変更 = 再インストールしなおし、ではなく任意のタイミングで再ビルドをかけるだけでよくなっているんですね。
ありがたや。
Pythonで「リストの指定した位置へ要素を挿入する」の動作を確認してみた

# 概要

Pythonで「リストの指定した位置へ要素を挿入する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/list/index7.html

# 実装

以下のファイルを作成しました。
```sample.py
mylist = ["Blue", "Red", "Green"]
# "White" をインデックス 2 の前に挿入
mylist.insert(2, "White")
print(mylist)
# "Black" を先頭に挿入
mylist.insert(0, "Black")
print(mylist)
mylist = ["Isu", "Uma", "Ashika"]
addlist = ["Ushi", "Inu"]
# 別のリストをインデックス 1 の前に挿入
mylist[1:1] = addlist
print(mylist)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
['Blue', 'Red', 'White', 'Green']
['Black', 'Blue', 'Red', 'White', 'Green']
['Isu', 'Ushi', 'Inu', 'Uma', 'Ashika']
```

# まとめ

何かの役に立てばと。
[Postman新機能] 他のAPIクライアントからの移行が超簡単！

今回は12月15日にリリースされたばかりの機能のご紹介です。
Insomnia、Thunder ClientやHoppscotchなど他のAPIクライアントからのデータ移行が格段にシンプルに行えるようになりました。（[ブログ](https://blog.postman.com/migrate-to-postman-from-other-api-clients/)）

手順は以下の通り。

1. 左側のサイドバーで、「インポート」をクリックします。 
1. 「Postmanへの移行」のドロップダウンから、Insomnia、Thunder Client、Hoppscotchの場合は「Other API Clients」を選択します。![Screenshot 2023-12-16 at 11.58.09 am.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722028/4f9c4392-ad5f-99b6-44b7-b3156d9eed09.png)
1. 選択したAPIクライアントからのデータが保存されているファイルまたはフォルダを選択します。
1. 「移行を開始」をクリックします。

補足：
- SoapUIの場合：XMLファイルを使用できます。
- Insomniaの場合：「Preferences > Data > Export > Export all data」からデータをエクスポートし、エクスポートしたフォルダを選択できます。
- Thunder Clientの場合：個々のエクスポートされたコレクションと環境ファイルを選択するか、以下のフォルダにあるすべてのデータを選択できます：
macOSの場合：`~/Library/Application Support/Code/User/globalStorage/rangav.vscode-thunder-client`
Windowsの場合：`C:\Users\{UserName}\AppData\Roaming\Code\User\globalStorage\rangav.vscode-thunder-client`
- Hoppscotchの場合：個々のエクスポートされたコレクションと環境ファイルを選択できます。 

今まで面倒だった他のAPIクライアントからのデータ移行とツールの一元化が一瞬でできるようになりました:rocket:
PostmanでHappy API testing!
概念から理解するTurbo Streamsを使ったリアルタイム通信

# はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー14日目です。

Turbo Stream(ActionCable)を使ったリアルタイム通信について学習したので、引き続きまとめます。

[こちらの記事](https://qiita.com/eichann/items/bc1ea15184b7bdc2b264)ではリアルタイム通信を実現する仕組みとしてWebsocketを紹介し、Action CableがWebsocketを扱うための機構であることを説明しました。

本記事では、もう少し具体的にリアルタイム通信を行うイメージを説明したあと、実際のコードでどのように書くのかを紹介します。

# Railsのリアルタイム通信の流れ

### 1.サーバ側でリアルタイム通信の準備をする
リアルタイム通信をするためには、サーバ側にてあらかじめ準備が必要です。どんな情報を送るのかなどを決めておきます。これを、チャンネル(チャネル？)と呼びます。RailsではActionCableにてChannelというクラスが用意されており、Railsアプリ内にこのクラスを継承したクラスを用意することで、準備ができます。

### 2.クライアントがサーバにリアルタイム通信を要求する
リアルタイム通信の流れとしてまずは、クライアントからサーバに「リアルタイム通信したいです！」と伝える必要がありますよね。
どうすれば良いかというと、Rails単体でアプリを作る場合はTurboライブラリがよしなにやってくれます。
Action Cableではクライアント側用にJavaScriptのライブラリも用意しており、それを活用するヘルパーメソッドを書くことで指定されたストリームからのデータの更新をリアルタイムで受け取るための準備を設定できます。これを、サブスクライブすると言います。

### 3.サーバが情報をクライアントにプッシュする
あとは、クライアント側に更新が必要な場合にサーバから通信を行います。ただしこれができるのは、「リアルタイム通信したい」旨を伝えたクライアントに向けてのみです。例えばあるユーザーがupdateアクションへリクエストし、それによりあるページに更新が必要となった場合、サブスクライブしているクライアント全てに対して(つまり、特定のページを「今まさに」開いているクライアントに対して)サーバから情報が送信されます。結果として、何も操作をしなくても通知が届く、メッセージが更新されるということができるわけですね。すごい！

この時情報を送信することを「ブロードキャスト」と呼びます。Turbo Streamsを使ったブロードキャストの場合、○○.turbo_stream.erbというファイルを元にレンダリングされたHTMLがレスポンスされます。

# 実際のコード例

### 1.サーバ側でリアルタイム通信の準備をする
実は、Turbo Streamをブロードキャストする場合はチャンネルを用意する必要はありません。
代わりにブロードキャストするための○○.turbo_stream.erbを用意する必要があります。こちらはこのあと紹介します。

### 2.クライアントがサーバにリアルタイム通信を要求する
例えば、とあるページでクライアントのページをサーバから情報を送る形で更新したい場合、ページの先頭に以下のように書いておきます。

```erb:index.html.erb
<%= turbo_stream_from "cats" %>
```

このようにすることで、このページを開いている間はサーバに「リアルタイム通信したいです！」と伝えることになります。
サーバは、ページからのリクエストを受けてチャンネルをサブスクライブさせます。

### 3.サーバが情報をクライアントにプッシュする
サーバが情報をクライアントに送るためには、アクション内に情報を送るメソッドを書いておく必要があります。以下のように書きます。

```ruby:○○_controller.rb
  def update
   if @cat.update(cat_params)
     @cat.broadcast_replace_to("cats")
     flash.now.notice = "ねこを更新しました。"
   else
     render :edit, status: :unprocessable_entity
```

この`@cat.broadcast_replace_to`メソッドが動くと、そのアクションのリクエスト元のクライアントだけではなくcatsをサブスクライブしているクライアント全てにサーバから情報が送信されます。送信されるのは、今回の例の場合`cats/update.turbo_stream.erb`ですね。

# 終わりに
Turbo Streamsを使うと、Rails側にChannelを用意しなくてもリアルタイム通信ができることがわかりました。

### 疑問点
Channelと併用することがあるのか、Action Cableの細かな仕様やオプション、できることなどがまだわからないので、調べてみます。
Amazon configとAWS System Managerで組織ルールをらくらく監査　その１

## 背景ときっかけ
・私の所属する組織はセキュリティルールがかなり厳しい
・組織内の多数メンバーに学習目的のAWS環境を提供することになった
・メンバーはきっとセキュリティルールを守ろうと、がんばるはず
・しかし、人間が行えば一定の漏れやミスが発生してしまうもの
・セキュリティルールを手作業で確認するのは**Undifferentiated Heavy Lifting**
・自動化は誰もがうれしいと思う。みんなが楽になる。
・時間は、価値を生むための仕事にまわす！
・なので、ルール確認を自動チェック、自動修復することにしました！

## Amazon config　AWS System Managerとは？
AWS Configは、AWSリソースの設定が設定したルールに準拠しているかどうかを自動チェックできます。自動チェックによりルールに準拠していない場合、AWS Systems Managerによって、自動修復することができます

## 自動チェックと自動修復の内容
#### AWS Configで、指定タグが付与されているか、自動チェック
学習目的のAWS環境は多数のメンバーにより、色々なリソースが随時作成されます。誰が作成したリソースか管理する必要がありますので、Ownerタグを付与し、値に個人名をいれてもらうルールがあります。だれがオーナーなのかわからないAWSリソースはセキュリティ上よろしくないですし、削除されずに残ると環境がちらかります。
例えば、メンバーがEC2を作成した際、Ownerタグを付与しないと、チェックNGとして検出する設定を行います
#### 指定タグが付与されていないEC2は、System Managerで自動的にインスタンス停止
上の自動チェックでNGになったEC2は、インスタンス起動したとしても、自動的に停止させます

#### AWS Configで、セキュリティグループのインバウンド許可に0.0.0.0/32が存在するか、自動チェックと自動削除
例えば、EC2のセキュリティグループで、SSH,RDPポートなどのインバウンド通信許可に、0.0.0.0/32（インターネットから全許可）が入っているのは危ないので、自動チェックします。自動チェックでNGになったセキュリティグループの0.0.0.0/32の設定行を自動的に削除します。


## Amazon configの始め方

#### リージョンを選択後、「1-Clickセットアップ」をクリック
※「今すぐ始める」でも良いのですが、こちらだと、AWS Config用のS3バケットを作ってくれて少し楽です。
※リージョンサービスなので、リージョン毎にセットアップが必要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/66c7a531-5499-d4cb-e4cf-c2eb9f096e9e.png)

#### 「確認」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/88eec256-9ddf-dcd5-13b5-1bb37f3ad5b0.png)

#### 準備ができました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141348/b9aae40b-4ffc-b4d4-c83e-c3b55ce36be7.png)

## つづく
次回、具体的にAmazon configの設定手順を書こうと思います
Query Parameter (GET) と HTML Form (POST) のリクエストパラメータ照会

- @ModelAttribute(最も推薦)、@RequestParam、request.getParameter()を使用してRequestパラメータを照会することができる。

## @ModelAttribute 
- オブジェクトを生成し、リクエストパラメータをオブジェクトに自動的に設定してくれる。
- Typeが合わないとBindExceptionが発生する。
- 
```java
@RequestMapping("/model-attribute") 
// @ModelAttributeは省略できる。
// public String modelAttributeV1(@ModelAttribute HelloData helloData) {
public String modelAttributeV1(HelloData helloData) {
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    log.info("helloData={}", helloData);
    return "ok";
}

// http://localhost:8080/model-attribute?username=test1&age=10
2023-10-02 09:49:06.758  INFO 73270 --- [nio-8080-exec-1] h.s.b.request.RequestParamController     : username=test1, age=10
2023-10-02 09:49:06.758  INFO 73270 --- [nio-8080-exec-1] h.s.b.request.RequestParamController     : helloData=HelloData(username=test1, age=10)
```
```java
@Data
public class HelloData {
    private String username;
    private int age; 
}
```

## @RequestParam
- パラメータ名でBindingする。
```java
@RequestMapping("/request-param-v2")
public String requestParamV2(
        @RequestParam("username") String memberName,
        @RequestParam("age") int memberAge
){
    log.info("username={}, age={}", memberName, memberAge);
    return "ok";
}

// HTTPパラメータ名が変数名と同じであれば(" ")省略可能である。
@RequestMapping("/request-param-v3")
public String requestParamV3(
        @RequestParam String username,
        @RequestParam int age
){
    log.info("username={}, age={}", username, age);
    return "ok";
}

// String、int、Integerなどの単純タイプであれば@RequestParamも省略可能である。
@RequestMapping("/request-param-v4")
public String requestParamV4(
        String username,
        int age
) {
    log.info("username={}, age={}", username, age);
    return "ok";
}

// requiredも設定可能であり、デフォルト値はtrueである。
// デフォルトValueも設定可能である。 defaultValueを使うと、requiredは必要ない。
// defaultValueは空文字の場合にも設定したデフォルト値が適用される。
@RequestMapping("/request-param-required-default")
public String requestParamRequiredDefault(
        @RequestParam(required = true, defaultValue = "guest") String username,
        @RequestParam(required = false, defaultValue = "-1") int age
){
    log.info("username={}, age={}", username, age);
    return "ok";
}

// リクエストパラメータをMapまたはMultiValueMapで照会することもできる。
// ?username=name1&username=2のようにパラメータ値が1つであることが確実でない場合は、
// MultiValueMapを使おう。
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap){
    log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
    return "ok";
}
```

##  request.getParameter() 
    
```java
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String username = request.getParameter("username");
    int age = Integer.parseInt(request.getParameter("age"));
    log.info("username={}, age={}", username, age);
    
    response.getWriter().write("ok");
}
```
【Swift】PopUpButtonの使い方

# Pop UP Buttonの使い方
StoryboardにPopUpButtonがあるものの使い方がわからずに苦戦したので、忘備録として書きます。

## ViewController
```swift
@IBOutlet var popUpBtn : UIButton!

func setupBtn(){
    popUpBtn.menu = UIMenu(children: [
        UIAction(title: "1つ目", state: .on, handler:{_ in
           
        }),
        UIAction(title: "2つ目", state: .on, handler:{_ in
        
        }),
        UIAction(title: "3つ目", state: .on, handler:{_ in
        
        })
    ])
    popUpBtn.showsMenuAsPrimaryAction = true
    popUpBtn.changesSelectionAsPrimaryAction = true
}
```
あとはViewDidLoadなどで`setupBtn()`を呼び出せばOKです。

## StoryBoard
1. 好きな場所にPopUpButtonを配置します。
2. ボタンとpopUpBtnを関連付けします。
   ※この時にButton内部のMenu　ItemとOutlet接続されてしまうとエラーがでます。
   ※必ずUIButtonと関連付けしてください。

## まとめ
簡単でしたね！
以上、PopUpButtonの使い方でした〜。
【ChatGPT有の自作GPTs】の紹介。ジョークものです。実用品ではごさいません。

  
　どうも、カーブミラーです。

　今回は、ChatGPTのMyGPTsで作成した作品です。実用品ではごさいませんので、ご注意を。

:::note info
本記事は、ChatGPTの自作GPTsの
　紹介です。ジョークものです。
　　あしからず。
:::

　まずは、
　　GPTsについて、ですね。

　簡単に言えば、
　　カスタムChatGPTのことです。

　あるいは、
　　業務対応ChatGPT、
　　　個人用ChatGPTかな。

　特殊用途用の
　　ChatGPTですね。

　深津式プロンプトで有名な
　　深津貴之さんが
　　　頑張って作成していますね。
***
　作り方は、
　　GPTBuilderとの
　　　やり取りにより、
　　　　完成します。

　しかし、
　　より具体的な機能を
　　　盛り込むためには、
　　　　細かく設定したり、
　　　　　Pythonコードを
　　　　　　書き込む必要があり、
　　　　　　　素人には敷居が高い。
***
　でも、
　　ジョーク程度や
　　　個人用ならば、
　　　　やり取りで作成する形で
　　　　　充分です。

　今回のGPTsも
　　そうして作成しました。

　食い物屋で、
　　店主は、絵文字でしか
　　　話しませんw

　DALL-E3を
　　使用していますので、
　　　注文をすれば、
　　　　出してくれます。

　それだけですw

　下記にリンクを
　　貼り付けます。

　起動する際は、
　　ChatGPTアプリを
　　　立ち上げて、
　　　　ログインして
　　　　　おいてください。
[ここは食い物屋。酒に飲まれる客は客でなし](https://chat.openai.com/g/g-q7vwjpmtN-kokohashi-iwu-wu-jiu-niyin-mareruke-hake-denasi)

　今回は、ここまで。
Pythonで時計アプリを作ってみた

こんにちは。こちらは[Qiitaのデフエンジニアの会アドベンドカレンダー12日目](https://qiita.com/advent-calendar/2023/deafengineers)です。
本当は１２日目にアップするはずでしたが、予約投稿を忘れていてすみません；；；

## はじめに
私は今まではPHPをメインにしていて、今年からPythonでアプリ開発の仕事に携わったばかりです。
なので今までいただいた案件もそんな多くなく、同僚や上司から色々とアドバイスを受けて勉強しつつ開発をしています。
そして一番最初に作ったのが時計アプリだったので、それを記念として書いてみることにしました。

## 時計アプリの作り方
時計アプリを作るのって難しそう、というイメージがあります。
でも作ってみると非常に簡単です！

### 前提
前提として、時計アプリを作るためには以下のライブラリが必要である。

・Tkinter

この「Tkinter」はPython標準ライブラリ。
そして、PythonでGUIアプリケーションを作成する際によく使われるライブラリなので覚えておくと良い。

### コード実行


```python
import tkinter as tk
import time

root = tk.Tk()
root.title("Clock")

clock = tk.Label(root, font=("times", 50, "bold"))
clock.pack()

def tick():

now = time.strftime("%H:%M:%S")

clock.config(text=now)

clock.after(1000, tick)

tick()
root.mainloop()
```


### コードの説明

１：Tkinterを入れる
```python
import tkinter as tk
import time
```

２：時計を更新するための関数を作成する
```python
def tick():
```

３：現在の日時取得
```python
now = time.strftime("%H:%M:%S")
```

４：1000msごとに関数（tick)を呼び出す
```python
clock.after(1000, tick)
```

## 番外編

Pythonは時計アプリが作れることが分かりました。
ちなみに今回はデジタルですが、実はPythonでアナログ時計も作れます。

それについてはこちらが詳しいので、是非こちらを参考にしてみてください！
[Pythonでアナログ時計を作る](https://qiita.com/ddside/items/5831980e9409e2b09ed5)

## デフエンジニアの会も応援してね

デフエンジニアの会も知ってください！

とはいっても私自身発言全くしていないのですが、こっそり見て色々と参考にさせていただいています。

こちらは私が去年のアドベントカレンダーで書いた記事です。
こちらも見てください。
[中途失聴エンジニアとして世の中を良くしたい！](https://qiita.com/Chihiro_0808/items/8f01e386b6a922b3060e)

それでは、また！
個人的に開発でよく使うChatGPTの使い方5つ

## 1.SQLを書いてもらう。

このテーブルとこのテーブルをこれで紐づけて、こことここの値の平均値を取ってSQLの結果として返してほしい。みたいな書き方をすると、多少修正は必要な場合はあるもののある程度の精度のSQLを返してくれます。
大枠を作ってくれるのでとても便利。

## 2.コードの書き換えをしてもらう。

例えばlaravelでformタグで記述されてるものを全部Formファザードで書き直さないといけない場合。
「このコードをgithubのFormファザードの形式に修正してください。」とお願いすると書き直してくれます。classとかidとかの指定も丸っと形式を直してくれるので便利です。
ただたまにデザインを省略してしまうことがあるので注意が必要です。一旦見直しましょう。

## 3.分岐の不整合を見つけてもらう
絶対どこかおかしいんだけどこんがらがりすぎてif文のどこが間違っているかわからない時、
「この場合ここ、この場合ここ、それ以外はこういう処理がしたいが、間違っているところを修正してほしい」というと修正してくれます。ただ書き方が正確でないと想定と違う挙動が修正されないことも多々あるので、確認は忘れないように。

## 4.概念が難しくてよくわからない時
専門用語で調べてもよくわからない単語は、「〇〇について小学生にもわかるように教えてください」とか書くとわかりやすく教えてくれることがあります。もっとわからなくなることもありますが、なんと無くイメージが掴めるのでおすすめです。

## 5.書き方が思い出せない時
phpの関数や、記述方法が思い出せない時、一旦ChatGPTに聞いてみます。それでほしい情報が得られなくても、googleなどで検索する際のキーワードを手に入れることができるので重宝します。


## 注意点
chatGPTが全て正しいことを言ってるわけではないので、鵜呑みにせずに自分でも生成されたコードや関数を再確認したり、本などで復習したりして理解を深めるのは大事です。

## 所感
「コードはAIが書いてくれる時代になるからエンジニアはいらなくなる」のような論も最近よく聞きますが、結局書いてほしいロジックはこちらで指定しないといけないので、コード自体は書かなくてもコードの構成を考える仕事は残るんだろうなと思いました。
仮にAIが全部書いたサービスが出てきたとしても、それを修正したり、保守したりは結局人の手が必要なので、全任せになるのはまだしばらくかかりそうな気がしています。

おしまい。
クライアントからサーバーにリクエストデータを転送する際に主に使用する方法

1. Query Parameter (GET)
    > localhost:8080/hello?**username=ABC&age=10**
    - **MessageBodyなしで**、URLのクエリパラメータにデータを含めて伝達する。
    - 検索、フィルター、ページングなどで多く使用する。

2. HTML Form (POST)
    ```html
    <form action="/hello" method="post">
    	<input type="text" name="username"/>
    	<input type="text" name="age"/>
    	<buttion type="submit">전송</button>
    </form>
    ```
    - 会員登録、商品注文のようにHTML Formを書く場合に使用する。
    - HTTPメッセージボディにGETのようなクエリパラメータ形式で伝達する。
    - POST HTML Form形式でデータを伝送する形式をapplication/x-www-form-urlencodedという。

3. HTTP message body (POST, PUT, PATCH など )
    - HTTP message body にデータを直接入れて要請する。
    - HTTP API で主に使用し、データ形式としてはJSON XML、TEXT などがある。
    - POST、PUT、PATCHなどをすべて使用できる。
    
    3.1. Content-Type : text/plain、単純テキストの場合
    ![스크린샷 2023-09-24 17.01.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567846/478a9a43-6cdb-8752-a213-632a86be5681.png)

    3.2. Content-Type : application/json, JSONの場合
    ![스크린샷 2023-09-24 17.06.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567846/31e91567-55f9-dd24-b6c8-835c6a6145cc.png)
【VSCode+SpringBoot】SpringBootでAPIを作る⑥

前回↓

https://qiita.com/NaN-jp/items/59c2a1e37114b4ec44de

# はじめに
今回は`Repository`を作っていきます
### Repository作成
`Repository`はデータアクセスを抽象化し、オブジェクトの集合へ格納・取得・検索するかのような振る舞いを提供します
demo直下に`repository`フォルダを作成してその中に`PersonRepository.java`を作成します
```java:src/main/java/com/example/demo/repository/PersonRepository.java
package com.example.springbootpostgresql.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.springbootpostgresql.model.Person;

@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
    
}
```
### ✨解説
◎`@Repository`
データ層のクラスに付与します
データベースにアクセスするために定義します
# おわりに
今回はRepositoryを作成しました
次回はServiceを作成したいと思います
AWS アクティブなリソースがないかタグエディタで検索する

# はじめに
消し忘れによる想定外の料金の請求を防ぐために、タグエディタを使用して現在アクティブなリソースを検索する手順を記載します。

公式サイトの手順
https://repost.aws/ja/knowledge-center/check-for-active-resources
料金については以下のサイトが詳細に記載しています。
https://iret.media/74015


# 対応方法
アクティブなリソースがないかタグエディタで確認します。
サービス > AWS Resource Groups をクリックする
左ペインのタグエディタを選択してリージョンは「All regions」リソースタイプは「All supported resource types]」を選択します。その後、リソースを検索ボタンを押しました。
CSV エクスポートを押しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/d9dce1f6-0f19-2a5a-5995-6db037e31cbf.png)

消し忘れがあると以下のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/aea4d59c-3cd3-02b1-0dfe-edd9f721a322.png)
デフォルト化する戦略【エンジニアデザイン心理学】




行動の実行はユーザーにとっては負担となってしまう。
物事を選択することでさえ、脳に精神的な負荷がかかってしまう。

だから、その選択をプロダクトが肩代わりすることでユーザーの行動はぐっと変えやすくなる。
**ユーザーが選択の合意以外は何もしなくてもよいという画面を作れるのが理想だ。**

**この戦略は限られた場面でしか使えない代わりに、非常に強力な戦略だ。**


## デフォルト戦略

行動をデフォルトにするために、ユーザーに代わって実行する内容を見極める。

例えば、ウェブサイトやインストーラーの画面であれば、促したい行動を代わりに実行してもよいか確認する。
その際に、デフォルトで「OK」にチェックを付けておくのだ。

<img src="https://3rdplanetblog.com/wp-content/uploads/2021/07/cp_ins_next.png">

### 具体例 : 確定拠出型年金のデフォルト戦略

確定拠出型年金のデフォルト戦略。

ユーザーがやるべきことは最小に抑えられており、入社時に配られる書類にサインするだけだ。
これだけで、確定拠出年金に使われるお金が給料から自動で引かれ、退職金用の口座に渡される。

この事例におけるデフォルト戦略の効果は大きく、デフォルト戦略実装前に比べて加入者は2倍となった。


### 具体例2 : デジタルカメラの機能でデフォルト戦略

デジタルカメラの機能でデフォルト設定を取り入れた事例。

- デジタルカメラを高機能にすればするほど、設定項目が増えて初心者の操作ミスを誘発した。
- デジタルカメラを低機能にするほど、上級者からの支持を得られない。

なので、よく考えられたカメラは「初心者向けのデフォルト機能」「上級者向けの高機能な設定画面」の二つを用意している。

同様の現象はソフトウェアのインストール画面でも見られる。


## ついでにする


ビタミンやミネラルを摂取してもらうのに最も効果的な方法について考える。

- 健康的なメリットを訴求する。
- 摂取量に応じてお金を払う。
- 有名人を起用してビタミンミネラルキャンペーンを行う

いろいろな選択肢があるが、最も手っ取り早いのが「本人が毎日食べているものに混ぜてしまう」ということだ。


### 具体例 : ヨード欠乏症

ヨード欠乏症とは、知的障害の主因であるが、予防可能な病気でもある。
このヨード欠乏症を予防するためには、ヨードを摂取することが一番だ。

加えて、ヨードを塩に添加するのには工数の増加が発生しない。
これらの要因から、ヨーロッパを中心として「塩にデフォルトでヨードを添加する」という案が打ち出された。

しかし、厳密には上記の策は失敗した。
「デフォルトでヨードを添加する」ということは、無添加の塩の選択肢がないに等しくなり、一部の人間の反発を招いたのだ。

**デフォルトの戦略ではユーザーに選択肢が与えられない場合、反感を買う可能性が高い**

いまでは、同意を得てヨードを添加した地域ではヨード欠乏症はめったに見られなくなった。
【Android】WebView参照時にTypeErrorで読み込みができない場合の対処法

# はじめに
Androidで実装する機能の中でほぼ必ずと言っていいほど使用する機能のひとつがWebViewですよね。
そんなWebViewですが、NextJSで実装されているようなWebページでたとえばアンダーバー付きのディレクトリを参照する必要がある場合など、そのままURLとして読み込むと以下エラーとなってしまいます。
```
"TypeError: Cannot read properties of null (reading 'getItem')", source:　https://XXXX 
```

今回はこちらのエラーの解消の仕方を備忘録的に残しておこうと思います。

# エラーの解消方法
解消方法は非常に簡単です。
WebViewはWebSettingsというパラメータを保持していますが、こちらに対し以下を設定してあげる形で対応可能です。

```main.kt
webView.settings.domStorageEnabled = true
```

https://developer.android.com/reference/android/webkit/WebSettings#setDomStorageEnabled(boolean)

以上になります。
こちらを追加することでTypeErrorを解消することが可能です。

# さいごに
気がつけば今年ももう終わりますね、年末年始のお休みを使ってWeb側の実装にも少し手を出そうと思います！
Ruby芸160チャレンジ(#31)正規表現のパターン利用

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
`#24`以降、しばらく題材的に取り組みづらいものが続くので`#31`まで飛ばします。

https://github.com/shellgei/shellgei160/blob/master/answer/31.md

```bash
$ sed -r 's/(<strong>)([^<]+)/\1\U\2/' iampen.txt
```

`<strong> </strong>`タグで囲まれた範囲内を大文字に変更する処理です。

## 解
```ruby
text = File.open('qdata/31/iampen.txt').read
puts text.gsub(/(<strong>)([^<]+)/) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).upcase}" }
```

## 所感
- マッチしたパターン`$1`、`$2`で使えば良いのですが、rubocopさんは`Regexp.last_match(n)`推しですね。この辺はフォーマッタにお任せしちゃいましょう。
Mindの変数の宣言の際の注意事項です（マインドTips）

# はじめに
以前、とある記事で話題になったMindの変数の宣言での注意事項についてまとめてみました。

# 対象読者

日本語プログラミング言語 Mindユーザーの皆さん。

# Mindの変数の宣言の際の注意事項
他のプログラミング言語の経験者の方ですと、つい下記のように書きたくなってしまうことがあるようです。

```mind:Mind
年齢は	変数。年齢に　34を　入れる。
名前は　文字列実体　長さ　１０桁。名前に　「花子」を　入れる、
特待区分は	変数。特待区分に　1を　入れる。
```

変数宣言の直後で初期値設定を同時に行っていますが、Mindではこのような書き方が出来ません。
変数の宣言は宣言文として記述し、初期値の設定は（いわゆる代入ですから）何らかの処理単語定義内で明示的な処理として行う必要があります。

```mind:Mind
年齢は	変数。
名前は　文字列実体　長さ　１０桁。
特待区分は	変数。
```

ただし、最初から変数の中身が決まっているなら（定数として）ストレートに書くことも出来ます。
```mind:Mind
年齢は、数値、34才。
名前は、文字列定数、「花子」。
特待区分は、数値、１区分。
```

34才…数値に続く後ろの文字列（この場合は単位表現）は無視されます。
文字列定数という概念があります。固有名詞とかは全部これで。
１区分…数値は全角でも半角でもOKです。

とはいえ、これでは変数じゃないのでちょっと使い勝手は悪いです。

# おわりに
いかがでしたでしょうか？Mindユーザーの皆様の参考になれば幸いです。
@mylifewithviolin さん、助言、有難う御座いました。
リクエストのヘッダー値、デフォルト値の照会

- AnnotationベースのSpring ControllerはSpringがサポートする様々なパラメータを使用することができる。
- @Controllerの使用可能なパラメータリストは、以下のマニュアルで確認できる。
    https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/arguments.html
    ```java
    @RestController
    public class RequestHeaderController {
    
        @RequestMapping("/headers")
        public String headers(HttpServletRequest request,
                              HttpServletResponse response,
                              HttpMethod httpMethod,
                              Locale locale,
    						  // すべてのHTTPヘッダーをMultiValueMap形式で照会する。
                              // Mapと似ているが、1つのキーに複数の値を受け取ることができる。
                              @RequestHeader MultiValueMap<String, String> headerMap,
                              // 특정 HTTP 헤더를 조회한다.
                              @RequestHeader("host") String host,
                              @CookieValue(value = "myCookie", required = false) String cookie
                              ){
    				log.info("request={}", request);
    				log.info("response={}", response);
            log.info("httpMethod={}", httpMethod);
            log.info("locale}", locale);
            log.info("headerMap={}", headerMap);
            log.info("header host={}", host);
            log.info("myCookie={}", cookie);
            return "ok";
        }
    
    // http://localhost:8080/headers 요청
    ...request=org.apache.catalina.connector.RequestFacade@29009f68
    ...response=org.apache.catalina.connector.ResponseFacade@27c76438
    ...httpMethod=GET
    ...locale=ko_KR
    ...headerMap={user-agent=[PostmanRuntime/7.33.0], accept=[*/*], postman-token=[ffa36d3b-4c1a-4f42-b5ad-181f504b3082], host=[localhost:8080], accept-encoding=[gzip, deflate, br], connection=[keep-alive]}
    ...header host=localhost:8080
    ...myCookie=null
    }
    ```
JavaParserを利用して、javaファイルをパースした際に、メソッド宣言された行の行番号を取得する

# 結論

JavaParserを利用して、javaファイルをパースした際に、メソッド宣言された行の行番号を取得するには、MethodDeclarationクラスのgetBeginメソッドを利用します。

ここで注意すべきは、getBeginで取得できる行番号はメソッドアノテーションを含むということです。たとえば、以下のようなメソッド宣言がある場合、getBeginで取得できる行番号はmethodXが記載されている行ではなく、`@Override`が記載されている行になります。

```java
@Override 
public void methodX(){...}
```

# 例

以下のようなファイルがあるとします。

```java:XXX.java
package path.to.example;

public class XXX {
    public void methodA() {
        // ...
    }
    
    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
    
    @Override
    @SuppressWarnings("all")
    public String toString() {
        return super.toString();
    }
}
```

このファイルをJavaParserを使ってパースし、XXXクラスのメソッド名とメソッド宣言されている行の行番号をコンソール表示します。

```java:Solution.java
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Paths;

import com.github.javaparser.Position;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

public class Solution {
    public static void main(String[] args) {
        try {
            CompilationUnit compilationUnit = StaticJavaParser.parse(Paths.get("XXX.java"));
            MethodDeclarationVisitor methodDeclarationVisitor = new MethodDeclarationVisitor();
            compilationUnit.accept(methodDeclarationVisitor, null);
        } catch (IOException e) {
           throw new UncheckedIOException(e);
        }
    }

    private static class MethodDeclarationVisitor extends VoidVisitorAdapter<Void> {
        @Override
        public void visit(MethodDeclaration n, Void arg) {
            Position position = n.getBegin().get();
            String text = "name=%s, line=%d".formatted(n.getName(), position.line);
            System.out.println(text);
            super.visit(n, arg);
        }
    }
}
```

実行結果は以下の通りになります。

```
name=methodA, line=4
name=equals, line=8
name=toString, line=13
```

# 環境情報 (pom.xmlの抜粋)

```xml:pom.xml
<properties>
  <maven.compiler.target>17</maven.compiler.target>
  <maven.compiler.source>17</maven.compiler.source>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
  <dependency>
    <groupId>com.github.javaparser</groupId>
    <artifactId>javaparser-core</artifactId>
    <version>3.25.6</version>
  </dependency>
</dependencies>
```
イマココYa-Hoo!+ ~登山女子による登山女子のためのアプリ~


# はじめに
弊社、株式会社エニプラでは毎月十数人のグループに分かれ社内活動や情報交換を行っています。
私の所属するグループで社内活動の一環としてヒーローズリーグ2023への出展を目標に活動してまいりました。

# 出展の内容
ヒーローズリーグ2023に出展する内容の検討を行った際に、
既存アプリのブラッシュアップを行うため2021年度にヒーローズリーグに出展したイマココYa-Hoo! ~登山女子による登山女子のためのアプリ~をブラッシュアップすることとなりました。

:::note info
**イマココYa-Hoo!~登山女子による登山女子のためのアプリ** とは
2021年度に作成した所属チームがヒーローズリーグに参戦した際に出展した思い入れのあるアプリです。
LINE APIやロボホンを使用して登山中の位置情報などを定期的に家族や友人に知らせてくれるように設計を行いました。
[イマココYa-Hoo! ~登山女子による登山女子のためのアプリ~](https://protopedia.net/prototype/2708)
:::

**イマココYa-Hoo!+ ~登山女子による登山女子のためのアプリ~**では下記のようなことが行えるよう設計しています。

・位置情報などを使用した定期的な連絡
・連絡したい内容に合わせてボタン1つで連絡できる機能
・思い出の保存機能
・山探しのサポート

もしよろしければ、下記紹介動画もご覧ください。
2024年度もアプリの新規開発やブラッシュアップを行えてより良いものを造れればと思っています。

[イマココYa-Hoo!+ ~登山女子による登山女子のためのアプリ~](https://protopedia.net/prototype/4845)

<iframe width="560" height="315" src="https://www.youtube.com/embed/bUf8czs9LmM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
文系エンジニアが成長するためにできることまとめ


## 文系出身エンジニアとして

文系エンジニアとして数年のらりくらり過ごして思った文系エンジニアができる成長戦略をまとめました。
理系エンジニアと対等に会話するとか、きちんと相手にしてもらえるようにすることが一つ重要になるかと思います。
そのために以下のことができると感じています。

幸い日本のIT業界では文系エンジニアでもやっていける環境もあるので、
業務を遂行しつつ様々なことに取り組んで成長すれば、光はあるかと。

文系でも理系でもエンジニアとして活躍できる業界になっていくといいですね。

## 資格取得
- 基本情報技術者試験、応用情報技術者試験
- AWS系やAzure系の資格取得
- DX検定、G検定など

資格否定派の人もいますが、文系エンジニアだと本当に何も理解していない人もいるので、
あったほうが知識の証明や能力の証明に少しでもなるので、ないよりはあったほうがいいかなと思います。

## ポートフォリオ作成
- プログラミング成果物
- テスティングなど周辺サービスの成果物

理解の深さで理系の方々に敵わないこともあると思うので、幅広く理解があるということも強みにしてもいいと思います。

## 競技プログラミングなど
- AtCoder
- ReetCode
- Paiza

## 人脈形成
-  カンファレンスへの参加
-  ハッカソンへの参加

## 学位取得
- 通信でコンピュータサイエンス学位を取る
    - 北海道情報大学
    - 放送大学

願書提出や事前準備の対応はありますが、経験や知識がなくても始めやすいと思います。

- 大学院の院試を受け、大学院の学位を取得する
    - 北陸先端技術大学院大学
    - 東京都立産業技術大学院大学

入学のために基本応用技術者試験らへんの知識は必要でしょうが、ネット情報では対策すれば文系出身者でも合格できらしいです（？）
卒業できれば理系エンジニアと対等に会話などしやすくなると思います。

- アメリカの学部や大学院のCSメジャーを目指す
    - University of the People（通信制大学）
    - ジョージア工科大学（CS修士課程？）

ネット情報ですが、通信や米国短大でのCS単位が認められて、アメリカの大学院に合格するケースもあるにはあるようです。

## 開発技術以外の能力をアピール
- 調整能力

他部署との調整は、文系出身者の目線を共有することで調整しやすくなる場合もあると思います。
非技術的な説明のしかたや抽象化した説明など、技術にあまり接していない人の目線で分かりやすくできればいいでしょう。
人間関係でチームに貢献することも重要。

- コミュニケーション能力
    - 要約力
    - プレゼン力

技術的な部分ではなく、発信する回数や質でアピールするのもいいと思います。
「技術力はそこそこだけど、発信力ある人」という評価をされている人もよくいると思います。
新しく入ってきたメンバーの教育係などで光るパターンも全然ありだと思います。
【AWS】VPC

# VPC(Amazon Virtual Private Cloud)とは
AWS上に作成できるプライベート仮想ネットワーク空間。AWS内に専用ネットワークを構築してAWSリソースを配置できる。
VPC内にリソースを作成するにはサブネット(大規模なネットワーク内の小さなネットワークで)が必要。またVPCはリージョン単位で作成でき，CIDR表記でネットワークを構築する。

VPCは複数のアベイラビリティゾーンをまたいで構築できるが，サブネットは各アベイラビリティゾーンごとに作成。

:::note info
**仮想ネットワーク**
ハードウェアで構成されたサーバーリソースを、仮想化ソフトウェアを使って抽象化したネットワーク
:::

:::note info
**CIDR表記**
198.51.100.xxx/24」のように「IPアドレス/サブネットマスクの1の個数」で表記する
:::

# サブネットタイプ
## パブリックサブネット
WEBサーバーなどインターネットとの通信が必要なEC2をパブリックサブネットに構築する。サブネット設定後，インターネットゲートウェイへのルーティングを設定することでパブリックサブネットを作成する。

## プライベートサブネット
インターネットとの通信ができない。NATゲートウェイを介することで，プライベートサブネット内でインターネットへの通信を行うことが可能になる。

# VPCの外部通信
VPCのリソースが外部通信をする場合は，ネットワークゲートウェイリソース(VPC外のネットワークと通信を行う際に経由する中継地点)を設置する。

## インターネットゲートウェイ
作成後にVPCにアタッチすることでVPCとインターネット間の通信を可能にする。VPCに1つ作成できる。通信元のリソースが**パブリックIPアドレス**を持っている必要がある。AWS側でスケーリング・冗長化されているので可用性が高い

:::note info
**パブリックIPアドレス**
動的に割り当てられるものと，固定的に割り当てられるもの(**Elastic IP Address**)がある。
:::

## NATゲートウェイ
プライベートサブネット内でインターネットへの通信を行う場合に，パブリックサブネットへ設置する中継用ゲートウェイ。単方向通信であり，プライベートサブネットからインターネットへ通信できるが，逆は不可能。

## 仮想プライベートゲートウェイ(VPN GW)
VPCとオンプレミス環境を接続するためにAWSに作成するネットワークゲートウェイ。

## カスタマーゲートウェイ
AWSとのVPN接続においてオンプレミス側に配置するゲートウェイ。オンプレミス環境で動的ルーティングを利用する場合は，**BGP(Border Gateway Protocol)**と呼ばれる**ピア接続**を利用してオンプレミスと接続する。

:::note info
**BGP**
ネットワーク同士を相互に結ぶ時に，互いのネットワーク経路情報をやり取りするための規格
:::

:::note info
**ピア接続**
対等な接続
:::

## VPCピアリング接続
独立した2つのVPCを接続し，プライベートアドレスを使って相互に通信する。冗長化された形で構築され，同じリージョンの別アカウントのVPCとも接続ができる。

## VPCエンドポイント
VPC内からAWSマネージドサービスにアクセスするためのサービス。

| エンドポイントの種類 | 説明 |
| ---- | ---- |
| ゲートウェイ型 | ルートテーブルの設定が必要 |
| インターフェース型 | AWS PrivateLinkを利用したエンドポイント。セキュリティグループを使って許可する接続を制御 |

## トランジットゲートウェイ
VPC間の接続を統合するアグリゲーション(集約型)のネットワーク管理サービス。

メリット
* オンプレミスとの接続で仮想プライベートゲートウェイが不要
* **クロスアカウントアクセス**を利用できる。

:::note info
**クロスアカウントアクセス**
特定のアカウントのAWSリソースに，別アカウントからのアクセスを許可する設定
:::

# 参考
https://www.rworks.jp/system/system-column/sys-entry/22121/
https://wa3.i-3-i.info/word11990.html
AWSの基本・仕組み・重要用語が全部わかる教科書
Instanaのエージェント別機能一覧

### 概要

IBMの可観測性(Observability)ソリューション Instanaのモニタリング用エージェント、
Instana Agentには複数種類があり、モニタリング対象によって利用するエージェントが違います。
エージェント毎にモニタリング対象と簡単なセットアップ方法をまとめておくと、便利かなと思い、マニュアルベースで一覧化してみました。

### エージェント別機能一覧
#### ホスト・エージェント

Instanaのホストエージェントには動的と静的の2種類があり、モードにはOFF、インフラストラクチャ、APMの3つが存在します。動的エージェントは自動更新が可能で、静的エージェントは更新されません。

### エージェントのタイプ
|エージェントのタイプ|	説明|
|-|-|
|動的エージェント|	起動時に最新のセンサーセットをリポジトリからダウンロードし、デフォルトで毎日自動更新します。バージョン固定による更新制御も可能です。新機能やバグ修正の迅速な取り入れに適しています。|
|静的エージェント|	リリース時の最新コンポーネントを含む自己完結型で、動的な更新機能がありません。ネットワークが制限された環境で推奨されますが、更新のためにはAnsibleやTerraformのようなツールを使用する必要があります。一般的には、可能な限り動的エージェントの使用が推奨されています。静的エージェントは更新が頻繁に行われないため、新機能や改善を逃す可能性があります。|

### ホストエージェントの動作モード
|動作モード|機能説明|
|-|-|
|OFFモード|このモードではホストエージェントは監視を行わず、Instanaバックエンドに定期的にアイドル状態を通知します。|
|INFRASTRUCTUREモード|ホストエージェントが基盤となるホストを監視し、Instanaがサポートするすべての技術に対してセンサーを活性化しますが、アプリケーションのトレースは行いません。|
|APMモード（デフォルト）|このモードでは、ホストエージェントがInstanaが提供する全体的な経験を提供し、サポートされるすべての技術に対する監視とトレースを行います。|

#### クラウド・サービス・エージェント

クラウドのアカウントと連携させ、各種クラウドサービスのモニタリングを行う。
クラウド環境モニタリング用の専用ホストに対して、ホストエージェントを導入し、AWSモードで動作させたり、各クラウドのセンサーを有効化させる必要がある。

|対象クラウド|セットアップ方法|
|-|-|
|AWS|ホストエージェントをAWSモードで実行|
|Azure|Azureセンサーの有効化が必要|
|GCP|GCPセンサーの有効化が必要|
|IBM Cloud|IBM Cloud用に特殊なセットアップが必要？（調査中）|
|Alibaba|Alibabaセンサーの有効化が必要|

#### サーバレス・エージェント

クラウド・サービス・エージェントと同様にホストエージェントを導入し、各クラウドと連携させる点は同じだが、
サービスによって追加でセットアップが必要になってくる。
「サーバレスなサービスをモニタリングするエージェント」という意味であり、
「エージェントレスなエージェント」という意味ではない点に注意。

|対象サーバレスサービス|セットアップ方法|
|-|-|
|AWS Lambda|Instana LambdaトレーサーのLambda関数への追加が必要|
|AWS Fargate|Fargateコレクターのセットアップが必要|
|Azure Functions|Instana Azure FunctionsトレーサーのAzure Functionsアプリケーションへの追加が必要|
|Google Cloud Run|Instana Cloud Native Buildpackによるセットアップが必要<br>（手動セットアップも可）|

#### Webサイト・エージェント

Webアプリケーションにモニタリング用のJavaScriptエージェントを組み込むことで利用する。
ホストエージェントによるAPM機能とは別にエンドユーザーモニタリング (EUM)、リアルユーザーモニタリング (RUM)を行うことができる。

|対象エージェント|セットアップ方法|
|-|-|
|JavaScriptエージェント|Instana UIで提供されるコードを組み込む（調査中）|

#### モバイル・エージェント

各モバイルアプリケーションの開発プラットフォームに組み込むことで利用する。
Webサイト・エージェントと同様にモバイルアプリケーションでも、エンドユーザーモニタリング (EUM)、リアルユーザーモニタリング (RUM)を行うことができる。

|対象エージェント|セットアップ方法|
|-|-|
|iOSエージェント|Swift Package Manager(Xcode)またはCocoaPodsでインストール|
|Androidエージェント|GradleプラグインとSDK依存関係を追加|
|ReactNativeエージェント|npmでパッケージ追加|
|Flutterエージェント|pub.devからパッケージをダウンロードして追加|

### まとめ

Instanaではモニタリングできるセンサーが300種類以上搭載されており、
ホストエージェントを入れればすぐモニタリング可能になるものが大半です。
とはいえ、各種クラウドサービスやEUM/RUMを行うとなると特別なセットアップが必要になるものもあります。
その辺がパッと分かればいいかなーと！

細かいセットアップ手順はマニュアルを参照してもらう必要がありますが、
マニュアルの項目ベースでまとめているので、検索しやすいかと思います。
（調査中のところは後日アップデート予定）

### 参考資料

[Instanaマニュアル](https://www.ibm.com/docs/ja/instana-observability/current)
イベントリスナーの登録法二種類

```javascript
//二種類のイベントリスナーの登録法

let hoge = function(){/*処理*/};
element.addEventListner("type",()=>{ hoge(); });
element.addEventListner("type",hoge);

//上だと、関数が引数をとる場合にも書くことができ、より柔軟性が高い。
//例
element.addEventListner("type",()=>{ hoge("abc"); });

//setIntervalも同様
setInterval(()=>{hoge();},1000);
setInterval(hoge,1000);

setInterval(()=>{hoge("abc");},1000); //柔軟性が高い
VSCodeでMarkdownファイルをhtmlに変換するおすすめの方法

本記事は、[めんどい太郎の Advent Calendar 2023](https://qiita.com/advent-calendar/2023/mendoitarou_first_calendar) 19日目の記事です。

# はじめに

この記事は初心者が書いています。

今回はVSCodeでMarkdownファイルをPDFに変換する方法をご紹介いたします。

# 拡張機能をインストール

まずはVSCodeに拡張機能をインストールします。

こちらの``Markdown PDF``という拡張機能です。

https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf

リンクを開いてインストールするか、Ctrl+Pで``ext install yzane.markdown-pdf``でもインストールできます。

# CSSファイルのダウンロードと加工

GitHubのMarkdownのCSSファイルをダウンロードします。

https://github.com/sindresorhus/github-markdown-css

こちらのレポジトリから
``github-markdown-dark.css``か``github-markdown-light.css``をダウンロードします。

ダークモードかの違いです。お好きな方を。

そうしたら、ダウンロードしたCSSファイルを開きます。

こちらの記事[^1]を参考にCSSファイルを加工します。

- すべての.markdown-を削除(空文字で置換すると楽)する
- code blockの折返しを設定する。

とのことです。

code blockの折り返しを設定するというのは

```CSS
body pre>code {
  padding: 0;
  margin: 0;
  font-size: 100%;
  word-break: normal;

  - white-space: pre;
  + white-space: pre-wrap;

  background: transparent;
  border: 0;
}
```

ということのようです。

加工したらOKです。

ここで**注意**

このCSSファイルは**ワークプレイス内においておく必要**があります。

おすすめはワークプレイスの一番上においておくのをおすすめします。

こんな感じ

```
.
├── Hoge
|   └── HogeHoge.md
├── hoge.md
└── github-markdown-dark.css
```

# 拡張機能の設定

VSCodeの設定を開きます。

Ctrl+,で開けます。

そうしたら右上の「設定(JSON)を開く」でJSONを開きます。

以下を追記します。

```JSON
"markdown-pdf.includeDefaultStyles": false,
"markdown-pdf.styles": ["./github-markdown.css"],
```

``./github-markdown.css``は``-dark``もしくは``-ligth``のどちらかを指定しておきましょう。

これでOKです。

# 変換する

あとはMarkdownファイルを開いて右クリックすると、``Markdown PDF: Export (html)``や``Markdown PDF: Export (pdf)``でHTMLファイルやPDFファイルに変換できます。

便利！

# 終わりに
GitHubのMarkdownのCSSを適応すると見た目が良くなります。

Qiitaの物があればよかったのですがしょうがない。

[^1]:[VS CodeでMarkdownをHTMLに変換する(Github Style)](https://qiita.com/youichi_io/items/cee2401a26e742fb447a)