OmniAICreator/Qiita-1.07M huggingface dataset:
AI時代を超える：死後も続くエンジニアライフプラン

## はじめに

「エンジニアとして生涯現役」そんな言葉を耳にしたことはありませんか？しかし、私が提案する最高のエンジニアライフプランは、それをさらに一歩進めたものです。AIが急速に発展する現代において、私たちエンジニアは「死後も活躍し続ける」という、これまでにない未来を描いてみました！

本記事では、AIと共に進化するエンジニアの役割、そして死を超えて社会に貢献し続けるという新たな視点からエンジニアライフプランについて考察します。

## 1. 未来のエンジニアリング：死を超えて

### 1.1 AI進化がもたらすエンジニアの役割の変化

現在、AI技術は日々進化を続けています。
例えば、

- GPT-4のような大規模言語モデルによるコード生成
- 機械学習モデルを用いた自動バグ検出と修正
- AIによる最適化されたシステム設計の提案

これらの技術により、エンジニアの役割は「プログラムを書く人」から「AIと協働してシステムを設計・改善する人」へと変化しつつあります。

### 1.2 定年を超えたエンジニアリングの可能性

従来の定年という概念を超え、エンジニアとしての知識や経験をAIに学習させることで、私たちの能力や思考をエミュレートすることが可能になると予想しています。これにより、死後も自分の「分身」がエンジニアとして活動を続けることができます。（きっと！）

例えば、私自身の経験を振り返ると、10年以上携わってきたプロジェクトの全ての記録、設計思想、トラブルシューティングの経験などをAIに学習させることで、私の「思考」を残すことができるのではないかと考えています。
そしてこれからは更に進化し、精度をあげてより自分に近似していくと思います。

## 2. 死後のエンジニアリング：その意義と準備

### 2.1 自己をエミュレートする技術

現在のAI技術を考慮すると、以下のような方法で自己をエミュレートすることが可能になると予想されます。

1. 日々の業務記録、意思決定プロセス、問題解決アプローチのデータ化
2. 個人の価値観、倫理観、思考パターンのAIモデルへの学習
3. 過去のプロジェクト履歴、成功事例、失敗事例のデータベース化

これらのデータをもとに、AIが「あなたらしい」判断や提案を行うことができるようになります。

### 2.2 死後も続く社会貢献の形

しかし、ここで疑問が生じるかもしれません。「なぜ死後も働く必要があるのか？」 確かに、生きている間の働く理由の多くは経済的な動機に基づいています。しかし、死後のエンジニアリングにおいて重要なのは、純粋に社会や未来、誰かの笑顔のために貢献することです。

私自身、エンジニアとして活動する中で、自分のコードや設計が誰かの役に立ったときの喜びを少なからず経験してきました。その喜びは決してお金だけでは得られないものです。死後も自分の知識や経験が誰かの役に立ち続けることができれば、それこそが究極の自己実現ではないでしょうか。

## 3. AI時代における人間エンジニアの価値

### 3.1 AIと人間の協働：人間らしさの真価

将来、AIは多くの面で人間の能力を超えるでしょう。しかし、そんな時代だからこそ、「この問題は人間の私に相談したい」と思われるような存在になることが重要です。

AIは論理的で最短距離の回答を導き出すことに長けていますが、人生や仕事において、必ずしもそれが最適解とは限りません。時には、

- 効率や利益よりも人の心を優先する判断
- 論理だけでなく、感情や直感を織り交ぜた意思決定
- 経験に基づく、泥臭くも温かみのあるアドバイス

が必要となる場面があります。

私自身、純粋に技術的な問題解決以上に、チームメンバーの気持ちを考慮した判断や、クライアントの本当の願いを汲み取ることの重要性を痛感してきました。

例えば、あるプロジェクトで技術的には最適な解決策があっても、チームの士気や長期的な成長を考慮して、あえて回り道をすることを選んだことがあります。結果的に、その経験がチームの結束力を高め、後のプロジェクトで大きな成功につながりました。

このような人間らしい判断や行動こそが、AI時代における私たち人間エンジニアの真価となるのではないでしょうか。論理や効率だけでなく、時には泥んこになりながらも、人の心に寄り添い、共に成長していく。そんな存在になることが、これからのエンジニアには求められるのだと思います。

### 3.2 最高のエンジニアライフとは

結局のところ、最高のエンジニアライフプランとは何でしょうか？
十人十色ですが、私は以下のように考えています。

1. 日々誠実にコツコツと努力を重ね、技術力と人間力を磨く
2. 常に学び続け、新しい技術やアイデアに対してオープンであり続ける
3. 自分の知識やスキルを他者と共有し、共に成長することを喜びとする
4. 将来の技術発展を見据え、自分の知識や経験をAIに学習させる準備をする
5. 死後も社会に貢献し続けられるよう、自分の「エッセンス」を残す


## まとめ：未来を見据えたエンジニアライフプラン

AIが発展する未来において、エンジニアの存在意義は「コードを書く人」から「社会や技術の発展に永続的に貢献する存在」へと進化していくと考えています。「コードを書く」ことは、その貢献を実現するための手段の1つに過ぎないでしょう。

この変化に適応し、真に価値ある存在であり続けるためには、以下の点が重要だと感じています：
1. 今を大切に生き、日々研鑽を積むこと
2. 技術スキルだけでなく、人間性も磨き続けること
3. 自分の知識や経験を後世に残す準備をすること
4. 常に社会や他者のために貢献する姿勢を持ち続けること

死後も活躍し続けるエンジニアという考えは正直少し大胆な妄想だったなぁと思っています。しかし、このお題のおかげで自分自身の在り方について深く考えるきっかけを得られました。

未来がどうなるかは誰にも分かりません。ですが、エンジニアを含むすべての人々が、より良い未来を願っていることは間違いありません。その思いを共有する一人として、これからも日々努力を重ねていきたいと改めて感じました。
【Figma Widget】Figma Widgetで使えるHooks まとめ

## はじめに
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/a0fa0949-ffca-ea26-a5c4-2ec2df8fd2a2.png)

みなさんは、Figma Widget を開発する際、FigmaにどんなHooksが使えるんだろう？と思ったことはありますか？

この記事では、そんな、Figma Widgetで使えるHooksについて解説しようと思います。

## Figma Widgetで使えるHooks

### useEffect

useEffect はウィジェットの状態が変化するたびに実行されるHooksです。
そのため、非同期タスクの実行、呼び出しのバンドル、またはイベント ハンドラーの副作用の統合が可能になります。

https://www.figma.com/widget-docs/api/properties/widget-useeffect/


```ts
useEffect(() => {
    // 処理を記載する
})
```

### usePropertyMenu
usePropertyMenuは、ウィジェットが選択されたときに表示するプロパティメニューを指定できます。

https://www.figma.com/widget-docs/api/properties/widget-usepropertymenu/

```ts
usePropertyMenu(
    [
        {
            itemType: "action",
            propertyName: "action"
        },
        {
            itemType: "separator"
        },
        {
            itemType: "color",
            propertyName: "color"
            selectedOption: color,
            options: [{option: "#e06666", tooltip: "Red"}, {option: "#ffe599", tooltip: "Yellow"} ],
        }
    ],
    ({propertyName, propertyValue}) => {
        if (propertyName === "color") {
            // 処理を記載する
        }
    }
)
```

### useStickable
:::note warn
useStickableは、FigJam専用のHooksです
:::

useStickableは、他のノードの上にドラッグされた時、他のノードにくっつくHooksです。
この動作は、Figmaのスタンプノードの動作に似ています。

https://www.figma.com/widget-docs/api/properties/widget-usestickable/

```ts
useStickable(() => {
    // 処理を記載する
})
```

### useStickableHost
:::note warn
useStickableHostは、FigJam専用のHooksです
:::

useStickableHostは、ウィジェットにスティッカブルが追加・削除されたときに、ウィジェットがコールバック関数を実行するHooksです。

https://www.figma.com/widget-docs/api/properties/widget-usestickablehost/

```ts
useStickableHost(() => {
    // 処理を記載する
})
```

### useSyncedState
useSyncedState は、ウィジェットのレンダリングが変更可能な状態に依存することを宣言し、キーとデフォルト値を指定すると、さまざまな状態にわたって、使用および更新できます。

https://www.figma.com/widget-docs/api/properties/widget-usesyncedstate/

```ts
const [count, setCount] = useSyncedState("count", 0)
```

### useSyncedMap
useSyncedMap は、useSyncedStateと同じように機能しますが、マップ全体が最後の値に上書きされるのではなく、マップ内の各値が最後の値に上書きされた値へ更新されます。
そのため、複数の人が一度にウィジェットを操作した時にウィジェットの状態を正確にレンダリングします。

https://www.figma.com/widget-docs/api/properties/widget-usesyncedmap/

```ts
const voteMap = useSyncedMap<number>("sessionIdToVotes")
```

### useWidgetId
useWidgetId は、`onClick`などのイベントハンドラでアクティブなウィジェットノードを参照するためのHooksです。

https://www.figma.com/widget-docs/api/properties/widget-usewidgetid/

```ts
const widgetId = useWidgetId()
```

## まとめ
この記事では、そんな、Figma Widgetで使えるHooksについて解説しました。
ぜひこの記事を参考にFigma Widgetで使えるHooksを使ってみてください。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
読んだ本書いていくやつ(メモ)

読んだ本を追記していくメモ
特定の分野に関する本とエンジニアに幅広く通ずる本を分けて書いていく
時間があれば要約記事をリンクにしていきたい

# 特定技術の本
* Androidアプリ開発の教科書 (Kotlin) 第３版
# 幅広い系の本
* カイゼンジャーニー(途中)
【備忘録】vSphereClient上からVMのディスクを追加したらOSが上がらなくなった

# 【エラー内容】
vSphere Client上で対象のVM（Linux）に対し、仮想ハードウェアの設定画面からディスクを追加した。追加後、VMを起動したところ、「OSイメージファイルがありません。」というエラーメッセージがVMコンソール上に表示された。

# 【確認したこと】
・追加したディスクをいったん削除してVMを起動 - 正常に起動した
・ディスクのプロビジョニングモードを現行ディスクに合わせた - 変化なし
・ホスト自体のディスク量を確認 - 問題なし

# 【原因】
追加したディスクが、既存ディスクに割り当てられているSCSI番号より若い番号に紐づいていた。だから既存ディスクにインストールされているOSを読み込むことができずに、起動が失敗。


# 【対応】
既存ディスクに紐づくSCSI番号より後の番号を指定。
SPIKEも戦える！VSCode拡張機能があればね

SPIKEプライムのプログラムをVSCodeで書ければ便利だと思いますよね。Pybricksを使うのが定石ですが、公式のファームウェアを使いたい場合は、以下のように行います。

:::note warn
SPIKEをVSCodeで使ったとて、複数のファイルを扱えないという致命的な問題は解決されません。複数ファイルを使うならおとなしくPybricksを使いましょう。
:::

## ダウングレード
バージョン3ではまだできないそうなので、バージョンを2に下げます。
通称SPIKE Legacyです。

https://afrel.co.jp/product/spike/technology-spike/basic/software-basic/54122/

アフレルが手順を公開しているので、これに従えば簡単にできます。

## 拡張機能
https://marketplace.visualstudio.com/items?itemName=PeterStaev.lego-spikeprime-mindstorms-vscode

すごくありがたい拡張機能が公開されているので、こちらを使います。Marketplaceに公開されているのでVSCodeで検索すれば見つかります。

## 初期設定
フォルダーを開いたら中に適当なPythonファイルを作ってもらって、右上の「LEGO Hub: Add File Header」を選びます。「Python (standard)」と「Python (advanced)」があります。standardは通常のSPIKE2のPythonそのままです。advancedは一度Scratchに変換することで、非同期処理を強くしているみたいです。

advancedは情報が少なくて調べ切れていないので、今回はstandardを使います。すみません。

そのまま進めると、以下のようなコメントがPythonファイルに追加されます。
```py
# LEGO type:standard slot:0 autostart
```
このボタンで行われるのはこのコメントの追加のみなので、使う必要がなければコピペかコメントを自分で書いてもいいですね。

## 実行
左下のメニューから「LEGO Hub: Disconnected」を押すと接続可能なデバイスのリストが出てくるので、繋げたいHubを選んでください。もう一度押すと接続が切断されます。

:::note warn
SPIKEのアプリを起動しているとそちらが優先されるため、VSCodeで接続できません。
:::

右上のメニューが増えるので、それぞれ解説します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/684a8bba-f3e4-9ca0-b868-7b169df7d9bd.png)
- 1番左の「Start Program」はSPIKEにすでにアップロードされたプログラムを遠隔で実行するボタンです。
- 2番目の「Terminate Runnning Program」は現在実行中のプログラムを強制終了します。
- 3番目の「Upload Program」は名前の通り、現在のプログラムをHubにアップロードします。上の設定で「autostart」をオンにしていれば実行も同時になされます。
- 4番目の「Show Log Terminal」はVSCode上でターミナルを表示してHubのログを確認できます。
- 1番右のボタンは先ほど説明したとおりです。

## 補完
プログラムは正常に動きますが、VSCode側では「インポート"spike"を解決できませんでした」といったインポートエラーが発生します。

補完をするにはこちらのGitHubのリポジトリを使うといいでしょう。クラスや関数の構成を疑似的に再現することで、VSCodeの補完が効くようになります。先ほど書いたようにSPIKEでは複数ファイルをアップロードすることができないので、競合によるエラーは発生しません。

https://github.com/dctian/lego-spike-prime-py

こちらをそのままzipとしてダウンロードし、VSCodeで開くだけで完了です。簡単に補完ができます。
main.pyの中身を消して、作業するのがいいでしょう。`hub`と`spike`フォルダは補完用なので消さないように注意してください。
【備忘録】Linux - SSH接続をグループ単位で許可する

# はじめに：

SSH接続を許可するユーザーをグループ単位で設定する必要があり、そのとき設定方法を勘違いしていたため、ここに備忘録として残す。

# SSH接続をグループ単位で許可：
グループ単位で許可するには、SSH設定ファイルで「AllowGroups」ディレクティブを定義する必要がある。

```text:SSH設定ファイル
/etc/ssh/sshd_config
```

```text:AllowGroups設定
AllowGroups [group1] [group2] ...

例えば：
「takenoko」というグループを指定するには
AllowGroups takenoko
```
設定した後は、SSHサービス再起動または定義ファイルのリロードをする必要がある。

```shell:SSH再起動/リロード
# サービスの再起動
systemctl restart sshd

# 定義ファイルの再読み込み（サービス停止はされない）
systemctl reload sshd
```

# 私が誤ったこと：
SSH定義ファイルに「AllowUsers」ディレクティブがすでに定義されており、これを考慮せずに「AllowGroups」を設定してしまったため、すべてのユーザーがSSH接続できなくなった。

:::note info
「AllowUsers」ディレクティブ：
ユーザー単位でSSH許可を指定する設定値
:::

「AllowUsers」と「AllowGroups」を設定すると、それぞれの設定（条件）に完全一致していなければ、対象ユーザーまたはグループでのログインができない。ログインするためには、それぞれの設定の条件を満たすように設定する必要がある。要するに「＆」条件。

```text:例
下記のユーザーとグループがあるとする。

ユーザー：
マイタケ（きのこ）、シイタケ（きのこ）、緑茶（お茶）、烏龍茶（お茶）　← ユーザー（所属グループ）　

グループ：
きのこ、お茶

マイタケとお茶グループとSSH接続できるようにするため、
「AllowUsers」と「AllowGroups」の設定が下記の通りにされたとする。

AllowUsers マイタケ
AllowGroups お茶

しかしこの設定では、マイタケはお茶グループに所属していないため、SSH接続はできない。
また、お茶グループの緑茶、烏龍茶は、AllowUsers に設定されていないため、SSH接続はできない。

「AllowUsers」と「AllowGroups」の２つを使って設定するならば、下記のようにする必要がある。

AllowUsers マイタケ、緑茶、烏龍茶
AllowGroups お茶、きのこ

この設定だと、シイタケ以外はSSH接続できるようになる。
だがこの設定の方法は手間がかかるため、
「AllowUsers」と「AllowGroups」どちらかを使用して制限をかけるべき。

運用としては、対象グループに所属しているユーザーのみSSH許可するとか。

AllowGroups　SSHグループ

または、SSH接続させたいユーザーを都度「AllowUsers」に追加していくとか。

AllowUsers マイタケ、緑茶、烏龍茶

```

:::note info
引用：[**【1.6. OpenSSH のセキュリティーの強化】**](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/securing_networks/making-openssh-more-secure_assembly_using-secure-communications-between-two-systems-with-openssh)
OpenSSH サーバーは、/etc/ssh/sshd_config 内のすべての Allow および Deny ディレクティブを渡す接続のみを許可します。たとえば、AllowUsers ディレクティブに、AllowGroups ディレクティブにリストされているグループの一部ではないユーザーがリストされている場合、そのユーザーはログインできません。
:::

# 参考URL：
・[**1.6. OpenSSH のセキュリティーの強化**](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/securing_networks/making-openssh-more-secure_assembly_using-secure-communications-between-two-systems-with-openssh)


# その他：
```terminal:rootユーザーによるSSH接続禁止設定
PermitRootLogin no
```

```terminal:プライマリグループを指定したユーザー作成
useradd -g プライマリグループ名 ユーザー名
```

```terminal:ユーザーとそのホームディレクトリとメールスプール削除
sudo userdel -r ユーザー名
```

```terminal:グループを作成
groupadd グループ名
```

```terminal:グループを削除
groupdel グループ名
```

```terminal:セカンダリグループをユーザーに追加
usermod -G セカンダリグループ名 -a ユーザ名
```

```terminal:全ユーザーアカウントのリストファイル（管理ファイル）
/etc/passwd
```

```terminal:全グループのリストファイル（管理ファイル）
/etc/group
```
日本語最強モデルEZOをColabで試す

# すごさをColabで試したい。
Gemma2の日本語性能の高さにたまげてたらあっというまに日本語継続事前学習モデルのEZOが登場しました。
https://huggingface.co/HODACHI/EZO-Humanities-9B-gemma-2-it
Gemma2はOllamaで触っていたのですが、EZOはまだOllamaに上がっていなかったのでColabで試しました。

## その前に
とか書いてから投稿する前に調べたらOllamaで上げてくださった方がいらっしゃったようです。
https://note.com/lucas_san/n/neb35a4060f2d
一応Commonのみ？っぽいのでこの記事はHumanitiesモデルを触るためということでご容赦ください。


# コード
大まかにはhuggingfaceのコード通りでいいのですがColabでは下記コードが必要そうです。

```python
!pip install transformers==4.42.3
!pip install accelerate
```

transformersのバージョンがColabでは若干古いのでアップグレードが必要です。
4.42.3にGemma2のアーキテクチャが取り込まれたようなのでそちらにアップグレードします。
また、それにともなってかaccelerateのインストールも必要です。なぜ依存ライブラリとしてインストールされないのかはわかってないです。

```python
from transformers import AutoTokenizer, AutoModelForCausalLM
import transformers
import torch
model_id = "HODACHI/EZO-Humanities-9B-gemma-2-it"
dtype = torch.bfloat16
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="cuda",
    torch_dtype=dtype,)
```
ここまででモデルのロードが完了します。

```python
chat = [
    { "role": "user", "content": "アニメ、シュタインズ・ゲートで主題となっているのはどのような概念でしょうか？" },
]
prompt = tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True)
inputs = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")
outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=300)
print(tokenizer.decode(outputs[0]))

```

下記が回答です。

```markdown
シュタインズ・ゲートの主題となっている概念は、主に以下の3つが挙げられます。

1. **因果律と時間旅行のジレンマ:**

   - 物語の中心は、時間移動装置「D-メール」を用いた時間操作によって引き起こされる、複雑な因果関係とパラドックスです。
   - 過去を変えようとする行為が、未来に予想外の波及効果をもたらす、時間旅行の倫理的な問題や、自己矛盾に陥る可能性を浮き彫りにします。

2. **選択と責任:**

   - 時間旅行によって、主人公の岡部倫太郎は何度も異なる未来を選択し、その結果に責任を問われます。
   - 彼の選択が、周りの人々の運命や、世界全体の未来に大きな影響を与えることを描き、個人の行動がもたらす影響の重さを強調しています。

3. **人間関係と愛:**

   - 時間旅行を通して、岡部と仲間たちは、愛する人々との絆を深め、失ったものを取り戻そうと奮闘します。
   - しかし、時間操作によって関係が歪んだり、新たな葛藤が生じることも描かれ、愛と喪失、そして人間関係の複雑さを表現しています。

これらの概念は、SF的な時間旅行の枠組みの中で、哲学的な問いと人間ドラマを巧みに融合させて、シュタインズ・ゲート
```

# 感想
9Bモデルで、Zero-shotの特定のアニメの質問にここまで精度良く返されて驚いています。固有名詞も正しいものが入っていて恐ろしいです。とうとうオープンモデルがここまで来てしまったのかという気持ちです。

速度もGPUはL4を使ったところ、11.5トークン/秒の速度で生成されました。

これならさまざまな分野で、特にAIキャラクターの分野で速度、精度ともに十分すぎるほど実用的なのではないでしょうか。

ローカルデバイスでのアシスタントも現実的です。今後もいろいろ遊んでいこうと思います。
Azure Static Web Apps を Azure Front Door 専用にアクセス制限を構成する

# Azure Static Web Apps を Azure Front Door 専用にアクセス制限を構成する

## 動機
Azure Static Web Appsをプライベート エンドポイントで非公開にして、Azure Front Doorからプライベート リンクさせるのが、アレなんだろうけどAzure Front DoorのPremium高いよ・・・って事で、お安く済ませること出来ないの？

## あるよ・・・「Azure Front Door を Azure Static Web Apps 用に構成する」
有るんかい！

https://learn.microsoft.com/ja-jp/azure/static-web-apps/front-door-manual?tabs=azure-portal&pivots=swa-afd-manual-afd

```staticwebapp.config.json
{
    "$schema": "https://json.schemastore.org/staticwebapp.config.json",
    "forwardingGateway": {
        "requiredHeaders": {
            "X-Azure-FDID": "フロントドアID"
        }
    },
    "networking": {
        "allowedIpRanges": [
            "AzureFrontDoor.Backend"
        ]
    }
}
```

## Azure Pieplineで動的にする

https://aadojo.alterbooth.com/entry/2021/11/04/090000
Micro Hardening Basic 参加記録

# 初めに
### Micro Hardening Basicとは
セキュリティをゲーム感覚で学ぶ競技 Micro Hardening の超入門編です。

参加者(皆様)は販売サイトの運営の主人公となり、迫りくる攻撃(不正アクセス、データ改ざんなど)から防衛し、スコアを競います。2人1組のチーム戦となります。(3人1組になる可能性もあります)


== 攻略難易度 ==
Micro Hardening v1, v2では販売サイトを運営するスキル (Webサーバやデータベース、Wordpress管理など) が求められますが、初学者にはなかなか難しかったという声からBasic版が誕生しました。感覚的な攻略推奨レベルは下記のとおりです。

Micro Hardening Basic (攻略推奨レベル 3) [今回]
Micro Hardening v1 (攻略推奨レベル 10) [7/28開催予定]
Micro Hardening v2 (攻略推奨レベル 15)

引用元（https://sc4y.connpass.com/event/316767/）

上記に書いてある通り**超入門編**、つまり**超初心者編**という前回のShield stoneで大戦犯をかました私にはうってつけの競技会でした。
メンバーは同じ学校の同級生と先輩の3人で挑みました。

# 本番までの準備
私と先輩が前日開催されたShield stone参加者ということもあり、初心者向けといいつつ難易度高いんじゃないかと考え、（Shield stoneが初心者向けといいつつ難易度高かった）チートシートの作成をして準備を整えていきました。といっても本番まで1週間しかなかったため、Shield stoneで使用したチートシートを流用するかたちでの作成でした。また、Micro Hardening参加者である先輩から基礎的なlinuc操作を教えてもらうなど準備を進めていきました。

# 本番
オンラインでの参加だったので、開始は12時から始まりました。12時から13時までは本競技会についての説明があり、13時から競技開始でした。

### 1セット目
1セット目は事前に決めいていたTodoリストを基に堅牢化を努めました。内容としては「rootユーザーへのssh接続拒否」「不要ユーザの削除」「ユーザーのパスワード変更」「wafの設定」などを中心に努めました。
45分と短い時間のため優先度の高いものから対策をしたのですが、その判断は正しかったようで順調に売り上げを伸ばし、売上上位に入ることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835880/0471ce4d-1f7f-ce21-ed05-b3296f28163b.png)
↑team16が自分たちのチーム

### 2セット目
2セット目では1セット目考えていた以上に対策をしていて、攻撃を見ることができなかったので「rootユーザーへのssh接続拒否」など最低限の対策だけをして攻撃を見ることにしました。
最低限の対策だけにしたが大きく売り上げは落ちていないので、基礎的な対策をするだけでいいのではないかと考えました。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835880/bbdd67f1-cfb4-693e-68c4-26ce6583f310.png)

### 3セット目
3セット目では1，2回目のセットを通して基本的な対策をしていれば売り上げを伸ばせることが分かったので基本的な対策をすぐに終わらせ、さらに別の対策をするようにしました。内容をいうと参加される方が面白くなくなるので言わないでおきます。
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835880/37de359f-dd86-e1bb-8980-a0ecbe6303d0.png)
team7と2000点差とがついてしまったので、原因を探していたのですが、わかりませんでした。実際なぜ2000点差ついたのかわかりませんが、アパッチを再起動したタイミングでクローラーが商品を買いに来てて売り上げに入らなかった、というのが私たちがだした結論です。

# まとめ
Sheld Stoneとは違い本当に初心者向けとでした。（Shiled stoneは超がついてないからあの難易度になったのか？~~全く初心者向けじゃなかった~~）超とつくだけの難易度だったのではないかと初心者ながらに思いました。
主催者の方が「事前資料に記載されている対策一覧さえできれば売り上げはだせる。その対策もGoogleなどで調べればすぐでてくるものだけ」という様なことを言っていたので
参加するときに掲げた目標が「**バックアップの取得をする**」だったのですが、スクリプトを実行してwww/html配下のバックアップの取得をすることができたのですが、crontabを使用して定期的にバックアップを取得することが出来なかったのが少し心残りです。
できなかったこともありましたが、3セット合計で売上1位だったので良かったです。

Micro Hardening v1,v2の参加したいけど自身が無いなという人はまずはBasicから参加して自信をつけてみてはどうでしょうか。とても楽しい競技会でした。運営の方々、先輩方ありがとうございました！次回も参加したいなと思います
【Go】Echoのルーティングをグループ化してミドルウェアを設定する

## はじめに
Echoでルーティングをグループ化して、それに対してミドルウェアを追加するのにはどうやってやるのだろうと疑問に思ったので、調べてみました。

## コード
まず、/admin以下をグループ化するために、g := e.Group("/admin") を追加。
またさらにadminの中でもグループ化したい場合は、g2 := g.Group("/users")と書く。
そして、グループ化の宣言の後にミドルウェアを追加してやる。
```go
package main

import (
	"log"

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	e.GET("/", func(c echo.Context) error {
		return c.String(200, "Hello, World!")
	})

	g := e.Group("/admin")
	// ログミドルウェアを追加
	g.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			log.Printf("Admin Middleware")
			return next(c)
		}
	})
	g.GET("/dashboard", func(c echo.Context) error {
		return c.String(200, "Admin Dashboard")
	})
	g.GET("/settings", func(c echo.Context) error {
		return c.String(200, "Admin Settings")
	})

	g2 := g.Group("/users")
	// ログミドルウェアを追加
	g2.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			log.Printf("Admin Users Middleware")
			return next(c)
		}
	})
	g2.GET("/list", func(c echo.Context) error {
		return c.String(200, "User List")
	})
	g2.GET("/create", func(c echo.Context) error {
		return c.String(200, "User Create")
	})

	e.Logger.Fatal(e.Start(":8080"))
}
```

## 動かしてみる
```zsh
curl http://localhost:8080/admin/dashboard

Admin Dashboard%
2024/07/12 10:08:28 Admin Middleware
```

users以下にアクセスすると、adminとusersの両方のミドルウェアが適用される。
```zsh
curl http://localhost:8080/admin/users/list

Admin Users List%
2024/07/12 10:10:22 Admin Middleware
2024/07/12 10:10:22 Admin Users Middleware
```

## 参考
- https://echo.labstack.com/docs/quick-start#middleware
paiza.ioでelixir その300

# 概要
paiza.ioでelixirやってみた。
高位合成、やってみた。
練習問題やってみた。
構想編。

# 練習問題
俺言語で、serial送信を実現せよ。

# 俺言語拡張仕様
変数iとjを導入する。

変数iは、"hello"を、"h", "e", "l", "l", "o"で返す。
変数jは、0x55を、0, 0, 1, 0, 1, 0, 1, 0, 1, 1で返す。
変数0は、クロックにつながっている。115200ボーのパルス
変数xは、serial出力。

# serial送信な、俺言語コード

helloを115200ボーで送信
```
10 x=0
20 i="hello"
30 j=i
40 #=j@0*200
50 #=o@1*70
60 #=50
70 a=j
80 #=a@1*110
90 x=0
100 #=120
110 x=1
120 #=o@0*30
130 #=120
200 #=200

```


以上。
効果的な議事録の取り方：会議を成功に導くポイント

# 効果的な議事録の取り方：会議を成功に導くポイント

## なぜ議事録が重要なのか？

### 記憶には限界がある

まず初めに、人は忘れやすい生き物です。「自分は記憶力が良いから問題ない」と思うかもしれませんが、会議の全参加者が同じように覚えているわけではありません。重要なポイントが後で曖昧になることもあります。

### 一貫したフォーマットの重要性

議事録は、全員が同じ情報を共有し、記憶の曖昧さを補うための最適な手段です。特に、参加者が多い会議では各自が異なる部分を覚えていることが多く、一貫したフォーマットで記録を残すことで、「あのときこう言っていた」という誤解や水掛け論を避けることができます。

## 議事録の基本要素

### 誰が、何を、いつ、どこで、なぜ

効果的な議事録には、基本的な5W1H（誰が、何を、いつ、どこで、なぜ、どのように）が含まれています。これにより、後から見返したときに全体像がはっきりし、会議の内容を簡単に把握できます。

### アクションアイテムと責任者

会議中に決定されたアクションアイテムと、それぞれの責任者を明確に記録します。これにより、誰が何をすべきかが明確になり、次の会議でのフォローアップがスムーズに行えます。

## 議事録作成のベストプラクティス

### 簡潔で明瞭な記述

議事録は簡潔で明瞭に書くことが重要です。冗長な表現を避け、ポイントを押さえた記述を心掛けましょう。箇条書きや見出しを使って、読みやすく整理します。

### リアルタイムでの記録

可能な限り、会議中にリアルタイムで議事録を取ることが理想です。これにより、重要なポイントを逃さず記録でき、会議後の編集作業も軽減されます。

### フォローアップと共有

会議が終わったら、できるだけ早く議事録を整理し、全参加者に共有します。これにより、記憶が新しいうちに内容を確認でき、必要な訂正や追加情報をタイムリーに反映できます。

## まとめ

議事録は、会議の効果を最大化し、情報共有のズレを防ぐために欠かせないツールです。基本的な要素を押さえ、ベストプラクティスに従って作成することで、会議の成果を確実に次に繋げることができます。
Git入門：具体的なワークフローと応用

Gitを使ったバージョン管理では、様々なワークフローや応用方法があります。この記事では、具体的なワークフローとその応用について記述します。

### 目次

1. フォークとプルリクエストのワークフロー
2. GitHub Actionsを使った自動化
3. Gitのコンフリクト解決のベストプラクティス

### 1. フォークとプルリクエストのワークフロー

### フォーク

GitHub上のリポジトリをフォークすることで、自分のアカウントにコピーを作成します。これにより、オリジナルのリポジトリに影響を与えずに変更を加えることができます。

### クローン

フォークしたリポジトリをローカル環境にクローンします。

```bash
git clone https://github.com/your-username/repo.git
```

### ブランチの作成

新しいブランチを作成し、変更を加えます。

```bash
git checkout -b feature-branch
```

### 変更のコミットとプッシュ

変更をコミットし、リモートリポジトリにプッシュします。

```bash
git add .
git commit -m "Add new feature"
git push origin feature-branch
```

### プルリクエストの作成

GitHub上でプルリクエスト（PR）を作成し、変更をオリジナルのリポジトリにマージするようにリクエストします。

### 2. GitHub Actionsを使った自動化

GitHub Actionsは、リポジトリに対する自動化タスクを実行するためのツールです。CI/CDパイプラインを構築するために使用されます。

### ワークフローの作成

`.github/workflows`ディレクトリにワークフローファイルを作成します。

`ci.yml`

```yaml
name: CI

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    - run: npm install
    - run: npm test
```

### 3. Gitのコンフリクト解決のベストプラクティス

### コンフリクトの発生

複数のブランチで同じファイルの同じ部分を変更した場合、マージ時にコンフリクトが発生します。

### コンフリクトの解消

コンフリクトが発生した場合、Gitはコンフリクトのあるファイルを表示します。これを手動で修正し、ステージングします。

```bash
git add <ファイル名>
```

### リベースとコンフリクト解消

リベース中にコンフリクトが発生した場合も同様に、コンフリクトを修正し、リベースを続行します。

```bash
git rebase --continue
```

### まとめ

この記事では、フォークとプルリクエストのワークフロー、GitHub Actionsを使った自動化、コンフリクト解決のベストプラクティスについて記述しました。これらのツールと手法を活用して、効率的でスムーズなチーム開発を目指します。
Unity VR開発でPC操作によってデバッグを行う

# はじめに
VRデバイスではなく、PC操作により、VR操作をするための方法を調べたので記事にします。


https://www.moguravr.com/xr-kaigi-2022-20/

# シミュレーターについて
シミュレーターだけ知りたいという方のために、先にシミュレータについて書きます。

調べたところ、以下の二つが該当しました。
- [MRTK](https://learn.microsoft.com/ja-jp/windows/mixed-reality/mrtk-unity/mrtk2/?view=mrtkunity-2022-05)
- [XR Interaction Toolkit](https://docs.unity3d.com/ja/Packages/com.unity.xr.interaction.toolkit@2.0/manual/index.html)の[XR Device Simulator](https://docs.unity3d.com/ja/Packages/com.unity.xr.interaction.toolkit@2.0/manual/xr-device-simulator.html)

今回の記事では、XR Interaction Toolkitを使う方法を紹介します。

### 手順
- Package Manager - Unity Registry - XR Interaction Toolkitをインストール
![スクリーンショット 2024-07-05 182631.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/09377531-ac41-5b2c-e850-f3310dba2c1f.png)
- SamplesのStarter AssetsとXR Device Simulationをインポート
![スクリーンショット 2024-07-05 182643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/4d209f67-0e7f-5d70-f219-b546cc6085c7.png)
- Assets/Samples/XR Interaction Toolkit/{version}/Starter Assets/Prefabs/XR Interaction Setup.prefabをシーンに配置する
- Assets/Samples/XR Interaction Toolkit/{version}/XR Device Simulator/XR Device Simulator.prefabをシーンに配置する

これで実行するとシミュレーション操作ができます。
（シーンにMainCameraが配置されている場合は消しておきましょう）
WordpressテーマArkheで置換して出力

# 概要
Arkheではパーツを読み込み時に
フックが用意されておりそれを使って
表示を上書きすることができます

## 実際のコード
```functions.php
add_filter('arkhe_part__header/logo', function($parts_content) {
    $tags_to_replace = [
        '<h1 class="l-header__logo has-image">',
        '<div class="l-header__logo has-image">'
    ];

    foreach ($tags_to_replace as $tag) {
        $parts_content = str_replace(
            $tag,
            str_replace('>', ' style="justify-content:center;">', $tag),
            $parts_content
        );
    }

    return $parts_content;
});
```

上記の例ではlogoを中央寄せしたかったので
「>」を「style="justify-content:center;">」
に置換しました。
【基本情報】ドラえもんシリーズ第2弾！　ドラえもんの世界で見る暗号方式とデジタル署名

# はじめに
こんにちは！新卒未経験エンジニア（３ヶ月）です。
最近、基本情報技術者試験を受験するために勉強しています。
そのテストに出題される暗号方式とデジタル署名についての内容になります。
ぜひご覧ください！

# 共通鍵暗号方式

ドラえもんとのび太くんは、ひみつ道具について秘密に話したいとします。
このとき、2人は特別な鍵（パスワードのようなもの）を事前に決めておきます。
ドラえもん「のび太くん、この鍵を使ってメッセージを暗号化するね。」
のび太くん「分かった、僕も同じ鍵を使ってメッセージを解読するよ！」
+ ドラえもんがひみつ道具についてメッセージを送るとき、この特別な鍵を使ってメッセージを**秘密のコード**に変えます。
+ のび太くんは**同じ鍵**を使って、その秘密のコードを**元のメッセージに戻す**ことができます。

# 公開鍵暗号方式

ドラえもんがのび太くんに秘密のメッセージを送りたいけれど、のび太くんと事前に鍵を決めていません。そこで、のび太くんは2つの鍵を持っています。

1. **公開鍵**（みんなに公開してもいい鍵）
2. **秘密鍵**（自分だけが知っている鍵）

のび太くんは**公開鍵**をドラえもんに渡します。

のび太くん「ドラえもん、この公開鍵を使ってメッセージを暗号化してね。」
ドラえもん「分かったよ。この公開鍵を使ってメッセージを秘密のコードにするよ。」
+ ドラえもんがこの**公開鍵**を使ってメッセージを**暗号化**します。
+ この暗号化されたメッセージは、のび太くんの**秘密鍵でしか**解読できません。

のび太くん「僕の秘密鍵でこの暗号化されたメッセージを解読しよう！」

# デジタル署名

のび太くんがジャイアンにメッセージを送るとき、**そのメッセージが本当にのび太くんからのものであるのか**を証明する必要があります。

1. **のび太くんがメッセージを作成する**
のび太くんはドラえもんに「ありがとう」と書いたメッセージを作成します。

2.  **のび太くんの秘密鍵を使って署名を作成する**
のび太くんは、自分の秘密鍵（これはのび太くんだけが知っている）を使って、そのメッセージに署名を追加します。この署名は、メッセージと秘密鍵を使って特別なコードを作ります。
◎のび太くん「僕の秘密鍵を使ってこのメッセージに署名をつけるよ。」
3. **メッセージと署名をジャイアンに送る**
のび太くんは、メッセージと一緒にデジタル署名もジャイアンに送ります。

4. **ジャイアンがメッセージを検証する**
ジャイアンは、のび太くんの公開鍵（これはみんなが知っている）を使って、メッセージと署名を確認します。
◎ジャイアン「この公開鍵を使ってメッセージが本当にのび太くんから来たのか確認してみよう!」
ジャイアンが公開鍵を使って署名を確認すると、のび太くんがそのメッセージを本当に送ったことが証明されます。また、メッセージが途中で変更されていないことも確認できます。

# まとめ

**共通鍵暗号方式**は、**同じ鍵**を使ってメッセージを暗号化・復号化する方法
（例：ドラえもんとのび太くんが事前に決めた秘密の鍵）

**公開鍵暗号方式**は、**2つの鍵**（公開鍵と秘密鍵）を使ってメッセージを暗号化・復号化する方法
（例：のび太くんがドラえもんに公開鍵を渡し、秘密鍵で解読する）

**デジタル署名**は、送信者がメッセージを本当に送ったことを証明し、メッセージが改ざんされていないことを確認する方法
（例：のび太くんが**秘密鍵**で署名し、ジャイアンが**公開鍵**で検証する）。
検索処理に使用するインデックス



+ [レコード変更した直後にsearchAndScreenPop()時の挙動について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmKBI)

レコードの修正結果は「着信によるsearchAndScreenPop()」の代わりに「グローバル検索（電話番号「A」）」でも同様にすぐに反映されない。しばらく待った後に実行すると期待通りのレコードだけを表示します。


:::note
■Salesforceさんからの回答
検索処理に使用するインデックスは、データ更新後に即時反映されず
インデックス作成用の処理がキューイングされ、サーバ側で順次処理が実行されます。そのため、変更直後に検索できず、しばらく時間が経過すれば検索できる、という状況ですと上記のキューイング中のまだインデックスが作成されていない状態に該当する事が推測されます。
 

■URL
http://sfsupport.blog.fc2.com/blog-entry-34.html
:::

使用していると気付くかと思いますが、新規のレコード、または編集した項目に関してはすぐに検索がヒットしないことがあります。
これはデータベースからより早く検索を実現するためインデックスがはられるまでにかかる時間の問題です。
【Terminal】shoptコマンドで便利なオプションを調べてみた

# はじめに
bashのシェルオプションを設定する「shopt」コマンドがあることを知り、作業を効率化できそうなオプションについて調べてみました。bashを使用されている方の参考になれば幸いです。

**開発環境**
・WSL2/Ubuntu環境

# shoptコマンドとは

**以下GNU.orgのサイトより引用**
>This builtin allows you to change additional shell optional behavior.

・shoptコマンドを使用することで、シェルのオプション動作を有効化/無効化、
といった変更(切り替え)が可能とのこと

・shoptコマンドは以下のコマンドを実行することで、シェルのオプション動作の
一覧を表示できます
```
$ shopt
```

```:コマンド結果
autocd          on
assoc_expand_once       off
cdable_vars     off
cdspell         on
checkhash       off
checkjobs       off
・・・(省略)・・・
```

autocadやcdspellなどが記載されている列がオプション動作、on/offが記載されている列が
有効(on)/無効(off)を示している列です。

# shoptコマンドの便利なオプション

### cdspell

cdspellオプションが有効化されると、ディレクトリのスペルに小さな誤りがある場合、
cdコマンドの際修正します。対象となる誤りは欠けている文字や余分な文字などです。

・以下コマンドでcdspellを有効化
```
$ shopt -s cdspell
```

・以下コマンドでcdspellを無効化
```
$ shopt -u cdspell
```

cdspellについて実際に何文字程度タイプミスが修正されるか試してみました。
結果としては、1文字のタイプミスは修正されましたが、2文字以上は修正を確認できませんでした。詳細は以下に記載しました。

```bash:
~/example$ ls  #ディレクトリ構成表示
ShoptSampleDir1  ShoptSampleDir2

~/example$ cd ShoptSampleDi1 #本来Dir1の所Di1と1文字タイプミス
ShoptSampleDir1
~/example/ShoptSampleDir1$ #ShoptSampleDir1に移動

~/example$ cd ShoptSampleD1 #本来Dir1の所D1と2文字タイプミス
bash: cd: ShoptSampleD1: そのようなファイルやディレクトリはありません
~/example$ #ShoptSampleDir1に移動出来ない

~/example$ cd ShoptampleDir1 #本来Sampleの所ampleと1文字タイプミス
ShoptSampleDir1
~/example/ShoptSampleDir1$ #ShoptSampleDir1に移動

~/example$ cd ShoptmpleDir1 #本来Sampleの所mpleと2文字タイプミス
bash: cd: ShoptmpleDir1: そのようなファイルやディレクトリはありません
~/example$ #ShoptSampleDir1に移動出来ない

```


### dotglob

dotglobオプションが有効化されると、ファイル名展開の結果に'.'から始まるファイル名を含めます。


・以下コマンドでdotglobを有効化
```
$ shopt -s dotglob
```

・以下コマンドでdotglobを無効化
```
$ shopt -u dotglob
```

ls *コマンドを使用する際にdotglobオプションの有効化・無効化でどのように結果が変わるか試し、'.'から始まるファイル名も含まれることを確認しました。詳細は以下に記載しました。

```bash:
~/example$ ls * #dotglobを無効化した際のls *
sample.txt  sample1.txt

~/example$ ls * #dotglobを有効化した際のls *
.sampledotglob  .sampledotglob1  sample.txt  sample1.txt

```

以下サイトではdotglobオプションを使用して、cpコマンドやmvコマンドの実行の際に'.'から始まるファイルも対象に含める方法が記載されており、非常に参考になりました。

https://qiita.com/suzuki86/items/5ac921a7b8d7eef23179


# 参考文献
本記事は以下情報を参考にして執筆しました。

https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html

https://qiita.com/tsubasaogawa/items/cb9baa2eb0d3ee6c5ca8

https://orebibou.com/ja/home/201704/20170411_001/
スタンフォード式疲れない「座り方」がエンジニア向けだった

## はじめに
先日、スタンフォード式疲れない体を読みました
疲労の予防や回復法など体を疲れさせないための知識が詰まっていました
その中で`座り方`にフォーカスした章があり、長い時間デスクワークを行う方々（タイトルではあえてエンジニアと書きました）に向いている内容だと思ったのでメモ書き程度で恐縮ですが書き記してみようと思います

https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%95%E3%82%A9%E3%83%BC%E3%83%89%E5%BC%8F-%E7%96%B2%E3%82%8C%E3%81%AA%E3%81%84%E4%BD%93-%E5%B1%B1%E7%94%B0%E7%9F%A5%E7%94%9F/dp/4763136879

## 疲れないためのポイント
デスクワークしていると体が硬くなって疲れてしまうのですが、下記のポイントを押さえて座ってみましょう
- 耳と肩の位置が一直線になっていること
    - 肩甲骨を真ん中に寄せるように締めると**肩こり防止にもなります！**
        - 肩回りにある上部僧帽筋もリラックスするので
            - 首がまっすぐ伸びて正しい位置に頭と首が整いだします！
- アゴをまっすぐ引く

![10adf0c6-ea36-4f06-9e0e-4dc50247c469.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/4cdbb874-31d5-8ab3-c4a9-1b5c0f6dae44.jpeg)
（イメージ図:DALL-Eより生成）

## 足を組む癖がある場合
そもそも体のバランスが崩れてしまっています
例えば体が右に歪んでいたら左に組むように脳が命令を下します
体のバランスを保つためですね　しかしこの繰り返しでますます崩れてしまうので注意しましょう

## ３０分おきに立つ
座ったままでいると、下半身の血流が滞り、むくみや疲労につながります
これがひどくなると**血栓**と呼ばれるエコノミークラス症候群の初期段階になってしまいます

### ひざ裏の**リンパ筋**を機能させる
リンパ筋には体の老廃物を処理する機能を持っています
座りっぱなしだとこの機能が滞ってしまい、老廃物が体内に巡ってしまいます
そうなると体全体に倦怠感が生じてしまいます　ゴミ出ししなければゴミが溜まって家が狭くなったり臭くなったり居心地が悪くなるイメージですね

そのため、疲れを予防するには３０分に１回は立ってリンパ筋を機能させる必要があります

## 立つのが難しい場合
気持ちはわかります　僕自身、作業に夢中になって２時間以上座りっぱなしになりますし、MTGがあると立てません
でもそんな時は**レッグ・タップ**を３０分に１セット行いましょう

### レッグ・タップのやり方
- 両足のつま先を床につける
- かかとを１５秒、ゆっくり上げたり下げたりする
- 次に両足のかかとをつける
- つま先を１５秒、ゆっくり上げたり下げたりする

上記のようにふくらはぎを動かす運動をすることで、ひざ裏のリンパ筋を刺激でき、全身の血の巡りが良くなって疲労物質の滞留を防ぐことができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/5c9ff6d7-3158-c9b0-7d94-9f7a7cfa3e01.png)
（イメージ図：[こちら](http://maemuki-blog.com/?p=13896)より引用）

## まとめ
今回はスタンフォード式疲れない体から引用した特にデスクワークを行う方々向けに座り方や疲労回復方法について書き記してみました

1. 正しい座り方
    - 耳と肩の位置を一直線にする
    - 肩甲骨を寄せ、肩回りの筋肉をリラックスさせる
    - アゴをまっすぐ引く

2. 足を組む癖の対策
     - 足を組むことで体のバランスが崩れることに注意し、できるだけ組まないようにする
    - 定期的に立つこと
    - 30分おきに立ち上がり、血流を促進する
    - 特に膝裏のリンパ筋を刺激することが重要

3. 立つのが難しい場合の対策
    - レッグ・タップを行い、ふくらはぎを動かすことで血流を促進する


これらを実践することで、デスクワークによる疲労を軽減し、より健康的な作業環境を保つことになるでしょう

## 参考文献

https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%95%E3%82%A9%E3%83%BC%E3%83%89%E5%BC%8F-%E7%96%B2%E3%82%8C%E3%81%AA%E3%81%84%E4%BD%93-%E5%B1%B1%E7%94%B0%E7%9F%A5%E7%94%9F/dp/4763136879

http://maemuki-blog.com/?p=13896
ビールの製造年月日のラベルを統計的に調べた話

* アサヒは「新しいほうがうまい」を主張してるからか[製造日は読める](https://xtaledit.blogspot.com/2023/03/blog-post.html)。AZC。

* サントリー。観察してみると必ず、/U,/N,/Sの表記がある。もしやと思い、前月、前前月あたりで、統計をとってみると、/Nの数＞/Uの数＞/Sの数。ということは「上旬＝/S, 中旬＝/U、下旬＝/N」。

ぼくが信じてるのは[コレ](https://www.jbja.jp/archives/320)です。とは言っても、体調、保存の仕方もある。選べないときもあるし、銘柄の好みもあるので柔軟対応かな
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482779/40173e10-a942-d21c-0fb7-3befec517463.png)

(https://www.jbja.jp/archives/320 から抜粋).
type-challenges 中級編5: Capitalize, Replace, ReplaceAll

# type-challenges 中級編5: Capitalize, Replace, ReplaceAll

## はじめに

[GitHubのtype-challengesリポジトリ](https://github.com/type-challenges)は、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回は中級編から3つの問題に挑戦します。

:::note warn
今回も前回に引き続き文字列の型が多いです、(実際に使うことあるかな...?)
:::


### 1. Capitalize

文字列の最初の文字を大文字に変換し、それ以外はそのままにする `Capitalize<T>` を実装してください。

#### 例

```typescript
type capitalized = Capitalize<'hello world'> // expected to be 'Hello world'
```

#### 私の回答

```typescript
type MyCapitalize<S extends string> = S extends `${infer C}${infer R}` ? `${Uppercase<C>}${R}` : S
```

#### 解き方

- ``S extends `${infer C}${infer R}`` という条件型を使い、文字列 `S` の最初の文字 `C` と残りの部分 `R` に分割します。
- `Uppercase<C>` を使って `C` を大文字に変換し、再度 `R` と結合して新しい文字列を作成します。
- もし `S` が空文字列などの特殊な場合、そのまま `S` を返します。

:::note info
簡単ですね！
:::

### 2. Replace

文字列 `S` に含まれる文字 `From` を `To` に一度だけ置き換える型 `Replace<S, From, To>` を実装してください。

#### 例

```typescript
type replaced = Replace<'types are fun!', 'fun', 'awesome'>; // expected to be 'types are awesome!'
```

#### 私の回答

```typescript
type Replace<S extends string, From extends string, To extends string> =
  From extends '' ? S :
  S extends `${infer P}${From}${infer R}` ? `${P}${To}${R}` : S
```

#### 解き方

- `From extends '' ? S` で、置き換え文字 `From` が空文字の場合、そのまま `S` を返します。
- `S extends `${infer P}${From}${infer R}`` という条件型を使い、文字列 `S` を `From` の前後に分割します。
- `P` と `R` を結合し、その間に `To` を挿入します。
- これにより、`From` を `To` に一度だけ置き換えた新しい文字列が生成されます。

:::note info
やってることは文字列取り出して再帰的に変換しているだけです！
:::

### 3. ReplaceAll

文字列 `S` に含まれる部分文字列 `From` を `To` に置き換える型 `ReplaceAll<S, From, To>` を実装してください。

#### 例

```typescript
type replaced = ReplaceAll<'t y p e s', ' ', ''>; // expected to be 'types'
```

#### 私の回答

```typescript
type ReplaceAll<S extends string, From extends string, To extends string> = 
  From extends '' ? S :
  S extends `${infer P}${From}${infer R}` ? `${P}${To}${ReplaceAll<R, From, To>}` : S
```

#### 解き方

- `From extends '' ? S` で、置き換え文字 `From` が空文字の場合、そのまま `S` を返します。
- ``S extends `${infer P}${From}${infer R}`` という条件型を使い、文字列 `S` を `From` の前後に分割します。
- `P` と `R` を結合し、その間に `To` を挿入し、`ReplaceAll<R, From, To>` を再帰的に適用します。
- これにより、`From` を `To` にすべて置き換えた新しい文字列が生成されます。

:::note info
ほとんどReplaceと変わりませんね！
:::

### まとめ

このように、TypeScriptの型システムを理解し、実際に型を実装することで、より安全で保守性の高いコードを書くことができます。ぜひこれらの課題を解いて、型力UPしてみてください。

### 参考記事

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [type-challenges GitHubリポジトリ](https://github.com/type-challenges/type-challenges)
Dify × Ollamaでローカル完結型生成AIアプリを作ってみた！

# はじめに
最近「Dify」の話題をよく聞きます。
ノーコードで生成AIを使ったアプリケーションが作れるということでエンジニアではない人が試してみているケースも多いようです。
今回はそんな「Dify」と「Ollama」というツール、そしてオープンソースのLLMを使ってローカル完結型のチャットボットを作ってみようと思います！

# Ollamaとは
Ollamaは、Llama 2などの大規模言語モデルをローカルで簡単に実行・管理できるオープンソースツールです。オープンソースLLMと組み合わせることでプライバシーを保護しつつ生成AIを利用することができます。

# オープンソースLLM
オープンソースLLMは、ソースコードが公開された大規模言語モデルです。誰でも無償で利用・改変でき、透明性が高く、カスタマイズも可能です。代表例にはMeta社のLlamaがあり、様々なアプリケーションの基盤として活用されています。
日本語に特化したLLMもあり、今回はその中から「Llama-3-ELYZA-JP-8B」を使ってみます。


# セットアップ
### 1\. Ollama
以下のページからダウンロード＆インストールします。

https://ollama.com/

### 2\. Llama-3-ELYZA-JP-8B（オープンソースLLM）
以下のページからモデルをダウンロードします。

https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF

ダウンロードしたモデルがある場所に「Modelfile」という名前のファイルを作成します。
Modelfileには以下のように記載しておきます。

``` text
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
```

Modelfileを作成したら以下のコマンドを実行してモデルを作成します。

``` bash
ollama create elyza -f Modelfile
```

### 3\. Dify
以下の公式ドキュメントに従ってDockerでローカル環境を用意します。

https://docs.dify.ai/getting-started/install-self-hosted/docker-compose

ログインしてホーム画面が表示されたら設定の「モデルプロバイダー」を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/5ae37c4e-e0b3-b248-a014-f46f384bdc71.png)

Ollamaの「Add Model」から設定画面を開き、以下の通り設定して保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/6a6bdbab-dcb2-c009-41a6-c2553166fedd.png)

※Dockerで起動しているためlocalhost:11434では接続できません！

# 作ってみる
それぞれのセットアップが完了したらDifyでワークフローを作っていきます。

### 1\. アプリ作成
ログインしてホーム画面が表示されたら「最初から作成」のワークフローを選択して「作成する」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/959009d4-4dae-e367-b6eb-e7ae311388eb.png)

作成すると以下のような画面になるためブロックをつなげてワークフローを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/116abdee-2b11-6813-30b1-40f7f2a75f13.png)

LLMのブロックには入力値をマスキングするプロンプトを入力しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/c1619ae7-fa14-4bbd-7da3-f76541a9cb3e.png)

### 2\. 試してみる
ワークフローが組めたら「実行」をクリックして試してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/9635da52-bcf7-7a6f-fe04-4e4ab3ed4b48.png)

こちらのジェネレーターでCSVデータを作成し、中身をinput欄に入れて「実行を開始」をクリックします。

https://testdata.userlocal.jp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/e13a49fa-764b-f5d8-23ea-b4a9c013da36.png)

無事結果が表示されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289475/f5d37265-4560-f3d7-038e-61493425be17.png)

結果の精度はイマイチでしたが、プロンプトを調整すればもう少し良くなりそうです。

# まとめ
ここまで読んでいただきありがとうございます！
今回はDifyとOllama、そしてLlama-3-ELYZA-JP-8BというオープンソースのLLMを利用して完全にローカルで完結した生成AIアプリを作ってみました！
実はDify×OllamaのコラボはDifyの公式ドキュメントにも手順が記載されています！

https://docs.dify.ai/v/japanese/guides/model-configuration/ollama

皆さんもぜひ試してみてください！
Mac: R のデータセットを使いたい--2

mac OS の Julia -- Version 1.10.4 (2024-06-04) で RDatasets が使えないという問題の，とりあえずの回避法。

正しいやり方かどうかわからないけど，とりあえずは動くので，やってみようと思う方は，自己責任でお願いします。

~/.julia/packages/TimeZones/@@@@@/src/types/timezone.jl
の，41行目の TimeZone から，何もせずに直帰する。
'@@@@@' はバージョンにより異なるディレクトリになるので，その都度調整が必要。

```Julia
function TimeZone(str::AbstractString, mask::Class=Class(:DEFAULT))
    return ##### この一行を加える
    tz, class = get(_TZ_CACHE, str) do
        ：
```
Material UIとTailwind CSSの併用

Material UIのコンポーネントを利用しつつ、Tailwind CSSも使いてー！！
でも併用出来ない！！！なんかないの！？

って探したら普通に見つかった

[Mateial UI も tailwind CSS も使いたい？ そんなあなたに『Material Tailwind』がおすすめ](https://ouni.jp/blog/material-tailwind/)
[Material UIをTailwind CSSのスタイルで上書きする方法](https://qiita.com/mo4g_dev/items/57c4a431df30895c5370)
[MUI+tailwindcssでButton componentが透明になる問題の解決策](https://asunaroblog.net/blog/641d6dacb5b671fd6673b3c5)
帰ったら早速試してみよう
.dockerignore でビルド時に不要なファイルを除外する

# はじめに
この記事では、`.dockerignore` の概要及び基本的な利用方法について記載します。

https://docs.docker.com/build/building/context/#dockerignore-files

# `.dockerignore` の概要
`.dockerignore` を利用すると、`.dockerignore` 内に追加されたファイルやディレクトリをビルダー（ex. Docker デーモン）に送信しなくなります。これにより、ビルド効率が改善されます。また、機密情報の保持にも役立ちます。

# `.dockerignore` の利用方法
次は `.dockerignore` の基本的な利用方法について記載します。

## ファイル位置
`.dockerignore` を置く位置は、ビルド時、引数として指定されたディレクトリになります。
例えば、以下の `compose.yaml` 及びディレクトリ構成の場合、`.dockerignore` は、`/dcoker/app` に置きます。

```compose.yaml
services:
  app:
    ports:
      - "${APP_HOST_MACHINE_PORT:-8000}:8000"
    volumes:
      - type: bind
        source: ./src
        target: /my-work
    build: ./docker/app
```

```powershell
├─compose.yaml
├─docker
│  ├─app
│  │  ├─.dockerignore # 追加
│  │  └─Dockerfile
│  └─db
└─src
```

## ファイルの記載方法
`.dockerignore` に以下の値を記載すると、`.git` や `.env` は、ビルダーに送信されなくなります。

```.dockerignore
**/.git
**/.env
```

# 参考
- [Build context](https://docs.docker.com/build/building/context/)
- [	鈴木亮「開発系エンジニアのためのDocker絵とき入門」秀和システム、2024](https://www.shuwasystem.co.jp/book/9784798071503.html)
94日目 RDSのコスト削減についてまとめてみる社畜S

## :file_cabinet:はじめに
こんにちは、社畜Sです。  
私のターンが回ってくるまでの1カ月の間に私はDB関連の業務に携わることになり、それに備えて情報収集を行っていました。  
その中で、RDSのコスト削減手法についてまとめる機会がありましたので、メモ書きがてら調査結果を皆さんに共有しようと思います。  
素人調査ということで、間違えている点もあるかもしれませんが、その際はコメントで指摘していただけると助かります:thumbsup:
## :file_cabinet:①インスタンスタイプを見直す
実際の運用状況に合わせてインスタンスタイプを変更することでコストを最適化できる。 

ただ費用を優先しすぎてインスタンスサイズを小さくしすぎると運用上のパフォーマンスにも影響が出るので、 **「Performance Insight」** などのツールを利用してデータベース全体のパフォーマンスを把握し、適切なインスタンスタイプを選択するのが大事 
 <dl>
  <dt>〇メリット</dt>
  <dd>・オーバースペックな部分をなくす事で、その分のコストが削減できる</dd>
</dl>
 <dl>
  <dt>〇デメリット </dt>
  <dd>・費用を優先しすぎるとパフォーマンスに影響を及ぼす可能性がある </dd>
  <dd>↳「Performance Insight」などのサービスで現状のパフォーマンスを分析して適切なインスタンスタイプを設定する必要がある </dd>
</dl>

## :file_cabinet:②オンデマンドインスタンスからリザーブドインスタンスへ変更する 

 **「リザーブドインスタンス」** はインスタンスを1年、もしくは３年で予約契約することで通常の利用料金より安価で利用できるサービスのこと  
     
支払い方法には「前払いなし」、「一部前払い」、「全額前払い」があり、 **3年契約の全額前払い** がもっとも削減率が高くなる 
インスタンスタイプなどの設定でまた変わってくるが、大体20％～60％のコストカットが見込める 　

ただ途中で解約ができないことや、事前にある程度スペックを固定してしまうことから運用の柔軟性に欠ける部分もある。 
有効に使うことができれば大幅なコスト削減が見込めるので、該当インスタンスの長期的な利用計画を確認し、検討することが大事！ 
後から適用することも可能らしいので、ある程度運用方針が安定してから適用するのも:o:　
</dl>
  <dt>〇メリット  </dt>
  <dd>・オンデマンドインスタンスに比べて大幅にコストを削減できる </dd>
  <dd>↳20％～60％のコストカットが見込める </dd>　
  <dd>・「前払いなし」「一部前払い」「全額前払い」から支払方法を選べる </dd>
  <dd>↳予算などに合わせて支払いができる。前払いありだと割引率UP </dd>
</dl>　
</dl>
  <dt>〇デメリット  </dt>
  <dd>・柔軟性が下がる</dd>
  <dd>↳事前にある程度インスタンスタイプなどを固定することになるので柔軟性が下がってしまう。
  <dd>ただし、サイズに関しては適応されるためスケールアップには対応している
  <dd>（例）db.r6g.xlarge → db.r6g.2xlarge　←この変更は可能 
  </dd>　
  <dd>・誤って購入してもキャンセルできない </dd>
  <dd>↳インスタンスタイプを間違えたなどのミスがあってもキャンセルできないので、購入時に注意が必要  </dd>
</dl>

## :file_cabinet:③使わないインスタンスを閉じる
起動しておくだけで勝手にコストが発生してしまうので、テストや開発環境など、本番環境以外のインスタンスは使わないときにちゃんと閉じておく 　

ただしRDSインスタンスは停止しても **７日間で自動的に起動する**   ので、忘れないようにEventBridgeなどで自動停止する仕組みを作る必要はあるかも 　　

また、インスタンスを停止していてもストレージ料金は発生してしまうようなので、検証用、開発用でも最低限の設定にすることを心掛けたい 
削除しておけば料金は発生しないので、再起動するめどがないなら削除しておくのが:o:（必要ならスナップショットも取っておく） 
## :file_cabinet:まとめ
というわけで、今回はRDSのコスト削減についての調査結果をまとめてみました。  
この記事が初めて軽量化について調べる誰かの助けになれたなら嬉しいです。  
私もわからないことはまだまだたくさんあるので、引き続き調査を進めていこうと思います。
type-challenges 中級編4: Type Lookup, Trim Left, Trim

# type-challenges 中級編4: Type Lookup, Trim Left, Trim

## はじめに

[GitHubのtype-challengesリポジトリ](https://github.com/type-challenges)は、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回は中級編から3つの問題に挑戦します。

### 1. Type Lookup

Union型から特定の型を属性を使って取得する汎用的な `LookUp<U, T>` を実装してください。

#### 例

```typescript
interface Cat {
  type: 'cat'
  breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}

interface Dog {
  type: 'dog'
  breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
  color: 'brown' | 'white' | 'black'
}

type MyDog = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`
```

#### 私の回答

```typescript
type LookUp<U, T> = U extends { type: T } ? U : never
```

#### 解き方

- `U extends { type: T }` という条件型を使い、Union型 `U` の中から特定の型 `T` を持つものを推定します。
- もし `U` が `{ type: T }` を満たす場合、その型 `U` を返します。
- そうでない場合は `never` を返します。

:::note info
inferが使えれば簡単。
:::

### 2. Trim Left

文字列を受け取り、先頭の空白を削除した新しい文字列を返す汎用的な `TrimLeft<T>` を実装してください。

#### 例

```typescript
type trimed = TrimLeft<'  Hello World  '> // expected to be 'Hello World  '
```

#### 私の回答

```typescript

type TrimLeft<S extends string> = S extends ` ${infer T}` ? TrimLeft<T>: 
  S extends `\n\t${infer X}` ? TrimLeft<X> : S 
```

#### 解き方

- `S extends ` ${infer T}`` という条件型を使い、文字列 `S` の先頭の空白を削除します。
- もし `S` が先頭に空白を含む場合、その空白を削除して再帰的に `TrimLeft<T>` を適用します。
- そうでない場合はそのまま `S` を返します。

:::note info
型でこんな文字列操作もできることは覚えておきましょう。（実務で使うかは謎ですが、、）
:::

### 3. Trim

文字列を受け取り、両端の空白を削除した新しい文字列を返す汎用的な `Trim<T>` を実装してください。

#### 例

```typescript
type trimed = Trim<'  Hello World  '> // expected to be 'Hello World'
```

#### 私の回答

```typescript
type Trim<S extends string> = S extends ` ${infer T1}` ? Trim<T1>: 
  S extends `\n\t${infer T2}` ? Trim<T2> : 
  S extends `${infer T3} ` ? Trim<T3>: 
  S extends `${infer T4}\t` ? Trim<T4> : 
  S 
```

#### 解き方

- `S extends ` ${infer T1}` という条件型を使い、文字列 `S` の先頭の空白を削除します。
- `S extends `\n\t${infer T2}` という条件型を使い、文字列 `S` の先頭の改行、タブを削除します。
- `S extends `${infer T} ` という条件型を使い、文字列 `S` の末尾の空白を削除します。
- `S extends `${infer T2}\n\t` という条件型を使い、文字列 `S` の末尾の改行、タブを削除します。
- これを再帰的に適用することで、両端の空白、タブを削除します。

:::note info
さっきと同じ。
:::

なんか無駄多いな、と思い他の人の実装を見てみたところ
```ts
type Space = ' ' | '\t' | '\n';

type Trim<S extends string> = S extends `${Space}${infer T}` | `${infer T}${Space}` ? Trim<T> : S;
```
みたいな書き方がいいみたいですね。

### まとめ

このように、TypeScriptの型システムを理解し、実際に型を実装することで、より安全で保守性の高いコードを書くことができます。ぜひこれらの課題を解いて、型力UPしてみてください。

### 参考記事

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [type-challenges GitHubリポジトリ](https://github.com/type-challenges/type-challenges)
Windows から rofi を実行して WSL にある GUI アプリケーションを起動する


## はじめに
Linux の rofi というランチャーアプリケーションで、様々な計算をしてくれる rofi-calc を動かしたくなって導入したのだが、そこに選択肢としてアプリケーションが出てきたのならば、そこから起動したくなるのが人の常。（ランチャーとして使う気は全くなかった。）

しかし、選択されたアプリケーションは実行されずに rofi が終了してしまう。これは解決せねばならないと、闘志を燃やすことになる。

## 背景
GUI Application をインストールすると、親切にショートカットを作ってくれますが、Windows Terminal からシェルに入ったら、そこに入り浸っている人なので、普段からコマンドを打って起動しています。

また、アプリケーションは自分で build して最新版を使うことが多いので、すでにあるアプリケーションのショートカットを参考にして、新規にショートカットを作っています。

## 自動で作られるショートカットのコピペでは起動できない

理由は、Windows 側で対象のプロセスを立ち上げただけなので...以下略

WSLg というか、 WSL の仕組みを理解してないと、私が他人に説明することができない、と判断しましたので、飛ばします。

## シェルの中で起動させる

シェルを起動させて、その中でターゲットのアプリケーション（プロセス）を起動させる。そうすれば、そのアプリケーションが、別のアプリケーションを起動させてから自身を終了しても、まだシェルの中にいるので、別のアプリケーションは動き続けることができる。

オペレーションシステムにおける、シェルの役割を理解しとくと、幸せになれるかもしれない。

## どのように記述するのか

PowerShell で、試行錯誤した。

以下に結果だけ書きます。

```shell
PS > wslg.exe -d Ubuntu-22.04 --cd "~" -- sh -c -i "rofi -show drun -normal-window"
```

wslg.exe をパラメーター無しで起動すると、使い方のダイアログが出るので、読んでみてください。

sh と言っても、実態は dash (Ubuntu の場合) なので、 `man dash` してマニュアルを読んでください。 ちなみに、 `man sh` すると dash のマニュアルが表示されます。（私は、 --help するより man する人です。）

パスが通っているところに wslg.exe があるので、フルパスで書かなくてもよい。

このコマンドを、ショートカットにコピペして終了です。

お疲れ様でした。

## おまけ

rofi を WSL から起動するときに -normal-windows をつけないと、挙動がおかしくなる。このオプションは設定ファイル (rasi) に入れることができなくて、起動するときのコマンドラインにつけるしかない。

Shell script を書く方法もあるのだが、 `sh -c -i` で済むことが多いので覚えておいて損はない。

読んでいただき、ありがとうございました。

## 参考文献
[【Linux】sh/bash/sourceの違い,bash/dashの違い](https://milestone-of-se.nesuke.com/sv-basic/linux-basic/sh-bash-source/ "sh, dash, bash, source")
Terraformを簡潔に理解

# Terraformを使ったIaCの基礎 :beginner:
Terraformは、HashiCorpが開発したオープンソースのInfrastructure as Code (IaC)ツールです。コードでインフラストラクチャを管理および提供することができ、クラウド環境やオンプレミス環境でのインフラのプロビジョニングを自動化します。この記事では、Terraformの基本的な概念と使用方法について解説します。

# Terraformの基本概念
### 1. Infrastructure as Code（IaC）
Infrastructure as Code（IaC）は、インフラストラクチャの設定をコードで管理する手法です。これにより、インフラのバージョン管理や再現性が向上し、手動操作によるエラーを防ぐことができます。

### 2. 宣言的構成
Terraformは宣言的構成を採用しており、最終的な望ましい状態を記述することで、Terraformがその状態に到達するためのアクションを自動的に計画および実行します。

### 3. プロバイダー
プロバイダーは、Terraformが管理するリソースの種類を定義します。AWS、Azure、Google Cloudなど、さまざまなクラウドプロバイダーをサポートしています。

#### Terraformのインストール
1. Terraformのダウンロードとインストール
公式サイト（https://www.terraform.io/）からTerraformをダウンロードし、インストールします。以下は、macOSの場合のインストール手順です。

```bash
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
```
2. インストールの確認
以下のコマンドを実行して、Terraformが正しくインストールされたことを確認します。

```bash
terraform version
```
Terraformの基本操作
1. Terraform設定ファイルの作成
Terraform設定ファイル（.tfファイル）にインフラストラクチャの定義を記述します。以下は、AWS EC2インスタンスを作成する基本的な例です。

```terraform
# provider.tf
provider "aws" {
  region = "us-west-2"
}
```
```terraform
# instance.tf
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}
```
2. 初期化
プロジェクトディレクトリで以下のコマンドを実行して、Terraformを初期化します。これにより、必要なプロバイダーのプラグインがダウンロードされます。

```bash
terraform init
```
3. プランの作成
以下のコマンドを実行して、現在の設定に基づいた実行プランを作成します。これにより、Terraformがどのような変更を行うかを確認できます。

```bash
terraform plan
```
4. インフラストラクチャの適用
以下のコマンドを実行して、設定ファイルに基づいてインフラストラクチャを作成します。

```bash
terraform apply
```
5. インフラストラクチャの削除
以下のコマンドを実行して、設定ファイルに基づいて作成されたリソースを削除します。

```terminal
terraform destroy
```
Terraformの状態管理
状態ファイル
Terraformは、インフラストラクチャの状態を管理するためにterraform.tfstateという状態ファイルを使用します。このファイルには、現在のインフラストラクチャの構成情報が保存されます。

リモートバックエンド
状態ファイルをリモートで管理することで、チームでの共同作業が容易になります。例えば、Amazon S3やHashiCorpのTerraform Cloudを使用して状態をリモートに保存できます。

```terraform
# backend.tf
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "path/to/my/key"
    region = "us-west-2"
  }
}
```
Terraformモジュール
モジュールの利用
Terraformモジュールを使用することで、再利用可能な構成要素を作成し、複数のプロジェクトで利用できます。

```terraform
# main.tf
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  version = "2.44.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["us-west-2a", "us-west-2b", "us-west-2c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  tags = {
    Terraform = "true"
    Environment = "dev"
  }
}
```

# 【まとめ】
Terraformを使用することで、インフラストラクチャのプロビジョニングをコードで管理し、自動化することができます。宣言的な構成と強力な状態管理機能により、信頼性と再現性の高いインフラの構築が可能です。

# 【参考】
https://www.lac.co.jp/lacwatch/service/20200903_002270.html
type-challenges 中級編3: Last of Array, Pop, Promise.all

# type-challenges 中級編3: Last of Array, Pop, Promise.all

## はじめに type-challengesとは

[GitHubのtype-challengesリポジトリ](https://github.com/type-challenges)は、TypeScript型システムの理解を深めるための型クイズ問題集です。高品質な型を作成することで、バグを減らし、プロジェクトの保守性を向上させることができます。今回は中級編から3つの問題に挑戦します。

### 1. Last of Array

配列 `T` を受け取り、その最後の要素の型を返す汎用的な `Last<T>` を実装してください。

#### 例

```typescript
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]

type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1
```

#### 私の回答

```typescript
type Last<T extends any[]> = T extends [...infer Rest, infer U] ? U : never
```

#### 解き方

- `T extends [...infer Rest, infer U]` という条件型を使い、配列 `T` の最後の要素 `U` を推定します。
- 配列 `T` の最後の要素が `U` として推定される場合、その型 `U` を返します。
- そうでない場合は `never` を返します。

:::note info
inferとスプレッド構文を使えれば問題無く解けますね
:::

もう一つの奇抜な型も思いついたので紹介します。

```typescript
type Last<T extends unknown[]> = T extends [...infer U, unknown] ? T[U['length']] : never
```
実際のjsで書くと
```ts
arr[arr.length - 1]
```

と書いたような書き方ですね

:::note warn
キモいので上の方がいいですね
:::

### 2. Pop

配列 `T` を受け取り、最後の要素を除いた配列を返す汎用的な `Pop<T>` を実装してください。

#### 例

```typescript
type arr1 = ['a', 'b', 'c', 'd']
type arr2 = [3, 2, 1]

type re1 = Pop<arr1> // expected to be ['a', 'b', 'c']
type re2 = Pop<arr2> // expected to be [3, 2]
```

#### 私の回答

```typescript
type Pop<T extends any[]> = T extends [...infer U, unknown] ? U : []
```

#### 解き方

- `T extends [...infer U, unknown]` という条件型を使い、配列 `T` の最後の要素を除いた部分 `U` を推定します。
- 配列 `T` の最後の要素を除いた部分が `U` として推定される場合、その型 `U` を返します。
- そうでない場合は空配列 `[]` を返します。

:::note info
Lastと一緒ですね。簡単。
:::

### 3. Promise.all

Promise ライクなオブジェクトの配列を受け取る関数 `PromiseAll` に型を付けてください。戻り値は `Promise<T>` である必要があります。ここで、`T` は解決された結果の配列です。

#### 例

```typescript
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

// expected to be `Promise<[number, 42, string]>`
const p = PromiseAll([promise1, promise2, promise3] as const)
```

#### 私の回答

```typescript
declare function PromiseAll<T extends readonly unknown[]>(values: T): Promise<{
  [K in keyof T]: Awaited<T[K]>;
}>;
```

#### 解き方

- 結果の型は `Promise<...>` で返す必要があります。
- 配列 `T` の各要素 `T[K]` に対して、`Awaited<T[K]>` を使用して、そのPromiseが解決された型を取得します。

:::note info
組込みの型`Awaited` 型を使用することで、Promiseオブジェクトの解決された型を簡単に取得できます。
:::

### まとめ

このように、TypeScriptの型システムを理解し、実際に型を実装することで、より安全で保守性の高いコードを書くことができます。ぜひこれらの課題を解いて、型力UPしてみてください。

### 参考記事

- [TypeScript公式ドキュメント](https://www.typescriptlang.org/docs/)
- [type-challenges GitHubリポジトリ](https://github.com/type-challenges/type-challenges)