OmniAICreator/Qiita-1.07M huggingface dataset:
Gitのローカルを戻す方法　〜Git statusで確認しよう~

## 見出し
この投稿は初投稿となります。温かい目でご覧いただくとありがたいです！
アウトプットの一つとしてQiitaを使ってみます！
今年の１６日から未経験のプログラマーとして働くのでGitを再度復習しようと思って投稿いたします。
Gitのローカルで間違えて変更してしまったものを元に戻す方法をまとめていきます。

## ステージングされていないGitの変更を元に戻す方法

まずGit statusコマンドで現在のGitの状態を確認します！

```ruby:new.html.erb
git status
On branch basic-login
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   app/views/users/new.html.erb
        
```
 (use "git add <file>..." to update what will be committed)
 となっているのでまたGitにはステージングされいません！

 間違えてGitの変更をした場合
```
git checkout <filename>
```
全て変更するにはこのコマンドを使います
```
git checkout .
```
結果をgit statutsで確認すると
```
git checkout app/views/users/new.html.erb
Updated 1 path from the index myapp % git status
On branch basic-login
nothing to commit, working tree clean
```
nothing to commit, working tree cleanとなっているので大丈夫ですね！

## ステージングされているGitの変更を元に戻す方法
git checkoutコマンドを使ってもステージングされいて元に戻せない場合もあると思いますが、その場合はこのコマンドを使いました
```
git checkout HEAD -- [ファイル名]
```
全てを変更する場合
```
git reset
```
こちらも再度確認していきます　　まずは参考のためにgit addしてgit statusで現在の状況を確認します。
```
git add .
myapp % git status
On branch basic-login
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   app/views/users/new.html.erb
```
先ほどと違いChanges to be committed:のところで次はコミットしてくださいというメッセージが出てるのgit addには成功しています。では先ほど紹介したコマンドを使います。
```
git checkout HEAD -- app/views/users/new.html.erb
myapp % git status
On branch basic-login
nothing to commit, working tree clean
```
元に戻りました!

## 未追跡のファイルがあり　git checkoutでローカルの変更を戻せない時
当時、私はgit checkout .コマンドを使って全ての変更を元に戻そうと思った時このような状況になり、元に戻すことができませんでした。
```
git checkout .
Updated 1 path from the index
git status
On branch basic-login
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        app/controllers/test_controller.rb
        app/helpers/test_helper.rb
        app/views/test/
        test/controllers/test_controller_test.rb
```
Untracked files:となっており未追跡のファイルが存在しているのでgit addコマンドを使ってステージングさせてから元に戻すかもしくは下記のコマンドを使いました。
ファイルを削除する方法

```
git clean -f
```

ディレクトリもファイルも一気に削除する方法
```
git clean -df
```


```
git clean -df
Removing app/controllers/test_controller.rb
Removing app/helpers/test_helper.rb
Removing app/views/test/
Removing test/controllers/test_controller_test.rb
git status
On branch basic-login
nothing to commit, working tree clean
```
【ネタ】そこのあなた、バグに苦しんでいませんか？

# 祈ればバグは無くなる⁈

面白いアスキーアートを見つけたので紹介します。
それがこちらのコメントアウト。

https://gist.github.com/edokeh/7580064

仏陀が座禅を組んでいるアスキーアートがコメントアウトで書かれています。
機械翻訳ですが下の文字は`仏陀の祝福 一度もないBUG`と書かれています。

他にもコメント欄には、バグが出ないよう十字架に祈るバージョンもありました。

```
#                        ____________
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#  _____________________|            |_____________________
# |                                                        |
# |                                                        |
# |                                                        |
# |_____________________              _____________________|
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |            |
#                       |____________|
#
#   Dear Heavenly Father,
#
#   I come before you with humble hearts, seeking your guidance and protection as I embark on this coding journey. 
#   I pray that the projects and files with this prayer may be free from bugs and errors, that it may serve its purpose flawlessly, 
#   and bring solutions and joy to those who use it. May your wisdom and understanding fill my minds, 
#   helping us to write clean and efficient code. Lord, grant us the patience and diligence to debug and refine my
#   work until it is perfect in your sight. I trust in your divine assistance and grace, knowing that with your help, 
#   I can achieve excellence in my endeavors. 
#
#   In Jesus' Name, Amen.
```

このコメントアウトをコードの先頭に記載すればバグは無くなるかもしれません。
OllamaのLLMモデルの実験的な並行実行の機能の紹介

# Ollamaの実験的な並行実行の機能の紹介

こんにちは、皆さん！今回は、Ollamaの最新リリース（v0.1.33）で追加された実験的な並行機能についてご紹介します。これにより、**複数のリクエストを同時に処理する能力**が大幅に向上しました。

https://github.com/ollama/ollama/releases/tag/v0.1.33

# 注意事項
あくまでも（v0.1.33）時点では実験的機能のため、動作が安定しない可能性があります。 運用環境での利用は慎重に検討してください。

# 新しい並行機能の概要

Ollamaの最新リリースでは、次の2つの環境変数を設定することで、新しい並行機能を利用できます。

1. **OLLAMA_NUM_PARALLEL**: 単一のモデルに対して複数のリクエストを同時に処理する機能
2. **OLLAMA_MAX_LOADED_MODELS**: 複数のモデルを同時にロードする機能

これらの機能を有効にするためには、以下の環境変数を設定して `ollama serve` を実行します。

例: bashの場合

```bash
OLLAMA_NUM_PARALLEL=4 OLLAMA_MAX_LOADED_MODELS=4 ollama serve
```

例: Windowsの場合
Windowsのシステムの設定で環境変数として設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/77c9e397-7930-0b92-33c6-180d7598faa7.png)


# 環境変数の設定方法
それでは、これらの環境変数をどのように設定するかを詳しく見ていきましょう。

## ステップ1: 環境変数の設定
まず、ターミナルで以下のコマンドを実行して環境変数を設定します。
```bash
export OLLAMA_NUM_PARALLEL=2
export OLLAMA_MAX_LOADED_MODELS=2
```

## ステップ2: Ollamaの起動
次に、以下のコマンドでOllamaを起動します。
```bash
ollama serve
```

これで、Ollamaは指定した設定で起動し、複数のリクエストとモデルを同時に処理できるようになります。


## ステップ3: Ollamaでllama3のチャット実行する

ターミナルを2つひらいて、以下のコマンドを実行して、llama3とのチャットを2個並列して実行します。

```bash
ollama run llama3
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/068942d4-2b6b-8d15-ce86-bce254d1b32c.png)
例: Windows環境で2個並列してチャットしている様子

# 実際の利用シナリオ

この新機能は、以下のようなシナリオで特に有効です。

- 大規模なデータ処理: 複数のクエリを同時に実行することで、データ処理のスループットを向上させることができます。

- リアルタイムアプリケーション: ユーザーからの同時リクエストに迅速に応答できるため、リアルタイム性が求められるアプリケーションに最適です。

- 複数モデルの利用: 複数のモデルを同時にロードすることで、異なるタスクに対して迅速に対応することができます。

# まとめ

Ollamaの実験的な並行機能は、複数のリクエストとモデルを同時に処理する能力を大幅に向上させる強力な機能です。環境変数を設定するだけで、これらの機能を簡単に利用できるので、ぜひ試してみてください。

この新機能についてもっと詳しく知りたい方は、公式ガイドを参照してください。

[公式リリースノート](https://github.com/ollama/ollama/releases/tag/v0.1.33)

# 参考

<iframe width="560" height="315" src="https://www.youtube.com/embed/8r_8CZqt5yk?si=slO44axyO61pLAjI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

チャンネル　Prompt Engineer　さんの動画がとてもわかりやすいです。
OllamaでLLMを動作させてみようとおもってるかたは、ぜひともチェックしてみてください。環境変数を設定して動作確認している様子を確認することができます。
Laravel SanctumのSPA認証 × Next.js(React) Axios で 'Request failed with status code 419', エラー解決

# はじめに

タイトルの通り、Laravel SanctumのSPA認証をNext.jsでやろうとした時にハマった部分の解決法を備忘録として書いておきたいと思います。

## 環境
- Laravel 9.52.16
- Next.js 14.2.3
- React   ^18
- Axios   ^1.6.8

### 今回の方法で解決するであろう状況

LaravelのSPA認証は正常にできているものとします。
その上、CORSの設定はできていて、フロントやPostmanでリクエストした時、レスポンスヘッダーで`X-XSRF-TOKEN`がある。

この条件下で、それでもaxiosでリクエストした時に`Request failed with status code 419`エラーが発生する場合、今回の記事が役に立つかもしれません。

それとは別で、ハマっていた時に見て回ったサイトのURLを最後に貼っておくので、この記事で解決しなくともそちらの記事を見れば解決するかもしれません。

## 解決法

#### 1 `axios.defaults.withCredentials`を設定する。

:::note alert
<font color="Red">**🚨`axios.create`で`withCredentials: true`を指定しても動きません。🚨**</font>
:::

**必ず、`axios.defaults.withCredentials`**　を記述してください。

例
```ts
    axios.defaults.withCredentials = true;
    await axios.get(url)...
```

#### 2 `withXSRFToken: true`および`xsrfHeaderName: "X-XSRF-TOKEN"`を設定する
こちらは`axios.create`内に記述してもOKです。(少なくとも私の環境では大丈夫でした)

例
```ts
export const api = axios.create({
    baseURL: API_URL,
    withXSRFToken: true, // 追記
    xsrfHeaderName: "X-XSRF-TOKEN", // 追記
    headers: {
        "Content-Type": "application/json",
    },
});
```


## おわりに
この2つの対処法を見つけるまでに時間がかかりました🥲
特に`withCredentials`をaxiosインスタンスに記述しても機能しないのはめちゃくちゃにハマりました...
この記事が役に立てば幸いです！

### もしかしたら役に立つかもしれないリンク集

https://stackoverflow.com/questions/69002516/axios-not-sending-xsrf-token-with-headers

https://zenn.dev/yudai64/articles/7caaa3c828b828

https://github.com/axios/axios/issues/587

https://laratech.jp/posts/laravel-419-error/

https://stackoverflow.com/questions/72370540/laravel-sanctum-api-httponly-cookie-has-been-rejected-for-invalid-domain

https://blog.sat.ne.jp/2022/09/09/spa-cors-cookie/

https://teratail.com/questions/smpmo3bbcee51z

https://stackoverflow.com/questions/71886290/laravel-9-cors-is-not-working-access-to-xmlhttprequest-has-been-blocked-by-co
AWSコンソール アクセスIP制限

## なぜ
セキュリティ要件が中、高のAWS案件ではAWSコンソールにアクセスする際、アクセス元のIPアドレスに対して制限をかける。

## 使用するAWSサービス
AWS Identity and Access Management

## AWS設定手順
以下権限でポリシーを作成(aws:SourceIpをアクセスするIPアドレスにする)

```json:policy
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*",
        "Condition": {
            "NotIpAddress": {
                "aws:SourceIp": [
                    "XX.XX.XX.XX/XX"
                ]
            }
        }
    }
}
```

上記で作成したポリシーをユーザとユーザグループにアタッチする。

## 設定後のテストアクセス
最初にアクセスし問題なく権限通りアクセスできているのを確認した後、ポリシーのSourceIPを適当なアドレスに変更し再度アクセスし操作ができないことを確認

<font color="OrangeRed">注意としてAdminで設定してしまうとほかのユーザでアクセスできなくなってします可能性があるので設定するアカウントは別途作成を行ってください</font>


## 以下参考
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html
[BigQuery] JavaScript UDF を Bun でバンドルしてみる

## 概要

BigQuery の [JavaScript UDF](https://cloud.google.com/bigquery/docs/user-defined-functions#javascript-udf-structure) は活用できていますか？
外部の package を import するようなコードはバンドルして GCS に置く必要がありますが、これって結構面倒ですよね。

Bun を使ったらシンプルかも？と思って試したので備忘録を残します。最終的なコードはこちら。

https://github.com/kitta65/qiita_bq_udf_js

## Bun の導入

ちまたの記事では [webpack](https://webpack.js.org/) が使われている印象ですが、 [Bun](https://bun.sh/) はそれも含めて代替するような JavaScript / TypeScript 向けの all-in-one なツールキットです。

とりあえずインストールしましょう。
他のインストール方法も確認したい方は[こちら](https://bun.sh/docs/installation)。

```sh
curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
```

UDF を書く前に以下のように空の package.json を作っておきましょう。
普通は `bun init` コマンドを使いますが、今回は設定なしでどこまで動くか試してみます。

```sh
echo '{}' > package.json
```

## UDF を書く

今回は YAML を JSON に変換する UDF を定義してみましょう。
YAML の解析を自力で実装するのは難しいので [js-yaml](https://github.com/nodeca/js-yaml) をインストールします。

```sh
bun add js-yaml
```

このとき bun.lockb というファイルが生成されます。これは npm でいう package-lock.json です。ただし bun.lockb はバイナリファイルなので、 Git で管理するなら[この辺り](https://bun.sh/docs/install/lockfile)を一読するべきです。


さて YAML を JSON に変換する処理はこんな感じでしょうか。
末尾の `console.log()` は不要な気もしますが、これがないと全体が dead code と判断され後段で tree shaking されてしまうんですよね。賢すぎる。

```js:yml2json.js
import * as yaml from "js-yaml";

const yml2json = {
  convert: (y) => {
    return JSON.stringify(yaml.load(y));
  },
};

console.log(yml2json);
```

## GCS に配置

先ほど書いたコードをバンドルしてから GCS に配置します。

次のコマンドを実行すると ./out/yml2json.js が生成されます。これには js-yaml のコードもバンドルされています。超簡単！

```sh
bun build ./yml2json.js --outdir ./out
```

後は GCS に置くだけです。 BUCKET_NAME は各々書き換えてもらうとして、こんな感じ。

```sh
gsutil cp out/* gs://${BUCKET_NAME}
```

そうすると SQL から以下のように実行できます。

```sql
create temp function yml2json(yml string)
returns string
language js
options (library = ['gs://BUCKET_NAME/yml2json.js'])
as 'return yml2json.convert(yml)'
;

select yml2json('value: string value'); -- '{"value":"string value"}'
```

## 補足

`bun build` について補足します。これは BigQuery に特化した JavaScript ファイルを作成するコマンドではありません。デフォルトではブラウザで実行するためのファイルを生成します（詳しくは[この辺り](https://bun.sh/docs/bundler#target)を読んでください）。

BigQuery はブラウザ独自の API も Node / Bun 独自の API も実行できないですが、とりあえずブラウザ向けにバンドルしておけば動くことが多そうです。

例えば以下のコードは明らかに Node 独自の API を使っていますが、先ほどと同様に（デフォルトのブラウザ向けに）バンドルして GCS に配置すると正常に動きます。

```js:base64.js
import { default as Buffer } from "node:buffer";

const base64 = {
  fromString: (s) => {
    const buf = Buffer.from(s, "utf8");
    return buf.toString("base64");
  },
};

console.log(base64);
```

```sql
declare input string default 'Hello, 世界';

create temp function string2base64(s string)
returns string
language js
options (library = ['gs://BUCKET_NAME/base64.js'])
as 'return base64.fromString(s)'
;

-- いずれも "SGVsbG8sIOS4lueVjA=="
select
  string2base64(input),
  to_base64(cast(input as bytes)), -- 一般的な関数で答え合わせ
;
```

どうもバンドルの過程で polyfill されて、独自の API が都合よく消えるようですね。

> Bun automatically polyfills certain Node.js APIs when imported in the browser such as node:crypto, similarly to Webpack 4's behavior. 
https://bun.sh/blog/bun-bundler#targets

## 最後に

まだ様々なケースを試したわけではないですが、わずかな設定でバンドルできるのはすごいですね。よければお試しあれ。
Notion数式で16進数→10進数変換


# 数式

```javascript
sum(split(prop("入力（16進数）"), "").map(
	ifs(
		current == "A", 10,
		current == "B", 11,
		current == "C", 12,
		current == "D", 13,
		current == "E", 14,
		current == "F", 15,
		current.toNumber()
	) * pow(16, length(prop("入力（16進数）")) - index - 1)
))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/92532b8a-5773-2df5-7cae-a42dd4bc70f2.png)


# Step By Step
## ① 文字列を１文字ずつの配列にする

```javascript
split(prop("入力"),"")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/e577848a-3f6d-225b-5af8-dbdb2f3817e1.png)

## ② １文字ずつ文字を数値に変換する

```javascript
split(prop("入力（16進数）"), "").map(
	ifs(
		current == "A", 10,
		current == "B", 11,
		current == "C", 12,
		current == "D", 13,
		current == "E", 14,
		current == "F", 15,
		current.toNumber()
	)
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/ae5253f7-fa24-5a77-5988-a0399df021ea.png)


## ③ 位に合わせて16の累乗を掛ける
```javascript
split(prop("入力"), "").map(
	ifs(
		current == "A", 10,
		current == "B", 11,
		current == "C", 12,
		current == "D", 13,
		current == "E", 14,
		current == "F", 15,
		current.toNumber()
	) * pow(16, length(prop("入力")) - index - 1)
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/090d2bdb-5d7d-1428-8996-fb08eaa643a9.png)

## ④ 合算する
```javascript
sum(split(prop("入力"), "").map(
	ifs(
		current == "A", 10,
		current == "B", 11,
		current == "C", 12,
		current == "D", 13,
		current == "E", 14,
		current == "F", 15,
		current.toNumber()
	) * pow(16, length(prop("入力")) - index - 1)
))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/ea1e2b91-bd9b-4aa9-9256-392178682c48.png)

# 使用例
16進数のカラーコードを10進数にすることができます。
先頭の#は、`toNumber`メソッドで値を返さないので無視されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578163/a684ea58-d6cf-f190-6030-a38735a132bc.png)


# 参考
https://www.notion.so/ja-jp/help/formula-syntax
GitHub ActionでPythonパッケージのPyPI公開を自動化する

poetryベースのプロジェクトでパッケージをPyPIに公開する一連の手続きをGitHub Actionで自動化する方法を備忘録としてまとめる。

## poetryによるパッケージング

以前はソースコードをパッケージとして配布するために`setup.py`を書く必要があったが、現在はその役割が`pyproject.toml`に集約されている。poetryでは`pyproject.toml`をベースにプロジェクトを管理するため、パッケージの開発から公開までをスムーズに行うことができる。

ディレクトリ構成は以下のようにsrc layoutに従うとする。

```
.
├── README.md
├── pyproject.toml
├── src/
│    └── your_package/
└── tests/
```
:::note
プロジェクトの一般的なディレクトリ構成として[flat layoutとsrc layout](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/)の2種類がある。pytestを利用する際にはsrc layoutが推奨されている（詳細は[こちらのリンク](https://docs.pytest.org/en/7.1.x/explanation/goodpractices.html#tests-outside-application-code)を参照）。
:::

### プロジェクト情報の記述

`pyproject.toml`の`[tool.poetry]`にプロジェクトの情報を記述する。この情報がPyPI上のページにも反映される。

```
[tool.poetry]
name = "your-package-name"
version = "0.1.0"
description = "package description"
authors = ["name <email address>"]
license = "MIT"
readme = "README.md"
repository = "repository URL"
```

記述項目の詳細はpoetryのドキュメントを参照。

https://python-poetry.org/docs/pyproject/

### PyPIへの公開

**1. 認証情報の設定**

[PyPI](https://pypi.org/)でアカウントを作成してAPIトークンを取得する。以下のコマンドでpoetryに認証情報を読み込ませる。

```bash
poetry config pypi-token.pypi <your API Token>
```

**2. パッケージのビルド**

`src/`以下のコードを配布形式にビルドする。以下のコマンドを実行すると、`dist/`に`tar.gz`で固められたもの（source distribution）とwheel（built distribution）が生成される。

```bash
poetry build
```

**3. PyPIへの公開**

以下のコマンドでビルドしたパッケージをPyPIに公開できる。

```bash
poetry publish
```

## GitHub Actionによる自動化

上記の一連の手続きを、GitHub上での[リリース公開](https://docs.github.com/ja/repositories/releasing-projects-on-github/managing-releases-in-a-repository)をトリガーとして自動的に実行するようなワークフローを定義する。

以下のyamlファイルを`.github/workflows/`に配置してリポジトリにpushする。また、[こちらのリンク](https://docs.github.com/ja/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository)に従って、PyPIのAPIトークンを`PYPI_TOKEN`という名前のシークレットとして登録する。

```yaml
name: Publish Package

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: JRubics/poetry-publish@v2.0
        with:
          pypi_token: ${{ secrets.PYPI_TOKEN }}
```

:::note
パッケージの公開については、Marketplaceで公開されているアクション[poetry-publish](https://github.com/marketplace/actions/publish-python-poetry-package)を拝借した。
:::

これによりワークフローが登録され、リリースを公開したタイミングで自動的にパッケージがPyPIへ公開されるようになる。

## 参考

https://packaging.python.org/en/latest/

https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

https://kk6.hateblo.jp/entry/2018/12/20/124151
XSERVERでドメインを取得し、AWSでホストゾーン登録するまで

こんにちは。takazonessです。
今回は、自身のHP開設にあたり、ドメインを取得し、AWSで管理するまでをやったので、記事として残しておこうと思います。

<h1>前提条件</h1>
・XSERVERのアカウントを作成済<br>
・AWSのアカウントを作成済

<h1>XSERVERでドメインを取得</h1>
まず今回は、XSERVERを使用し、ドメインを取得しました。
別サービスとして、お名前.comなどもありますが、個人的に管理ページの仕様などが好きじゃないので、今回はXSERVERを使い、ドメインを取得しました。<br>

まず管理ページにログインします。
右上のサービス管理→Xserver Domainの順番で進みます。
![0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/696e29f2-8ab5-2bb2-d946-a346917a14ce.png)
下記のページが出たら、ドメイン取得をクリックします。
![0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/e4c18ab9-d84a-7ea4-7263-ede565433e99.png)
今回は takazoness.com を取得しようと考えていたので .com を指定します。(取りたいトップレベルドメインを選択してください。)
ドメインを検索するをクリックし、下記画面のように進みます。
![0003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/f5da7925-99ea-2606-b4d4-e742d8fdd030.png)
検索結果から、取りたいドメインを選択し、支払いに進みます。
![0004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/1fd09b1a-0c8b-4ca0-2974-d87018864de3.png)
支払いを完了すると、下記の画面のようになります。
![0005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/3d9765ee-d607-393e-6884-051df668f769.png)
ドメイン取得完了のメールも来ます。
![0006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/dd44de7c-58c5-69eb-e4cb-61c159ad4b73.png)
無事取得ができ。ドメインのページへ行くと、ドメインが追加されていることがわかるかと思います。
今回はネームサーバーをAWSのものに変更するので、左側の ネームサーバー設定 をクリックします。
![0007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/59449079-3409-01bc-a5c0-4dcd8fb90621.png)
下記のような画面になるので、ネームサーバーを変更したいドメインを選択します。
![0008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/a15dcbc4-8b62-620e-5459-b55d7ab0d422.png)
ここでAWSの設定に行きます。AWSアカウントにログインし、コンソール画面を開きます。
![0009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/a79c4610-b1d1-2198-fea1-dfa727e9bd86.png)
Route 53のコンソール画面に移動し、「ホストゾーンの作成」をクリックします。
![0010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/4eda5e20-7000-4e93-8b52-5a38dda3bc8c.png)
登録したいドメイン名を入力し、タイプは「パブリックホストゾーン」を選択し、ホストゾーンの作成をクリックします。
![0011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/8af923f8-7f59-ae22-5628-e85e8bed4809.png)
無事作成できると、作成したホストゾーンの詳細が見れるようになると思います。「NS」という区分に書いてある値をすべてコピーします。
![0012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/013b712e-831e-eca2-65cc-b45eaab4d4b1.png)
コピーが完了したら、Xserverドメインの管理画面へ移動し、ネームサーバー設定を選択し、コピーした情報を貼り付け、確認画面へ移行をクリックします。
![0013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/b26efb98-13a6-d744-441f-404e926711be.png)
下記画像のようになりますので、設定を変更するをクリックします。
![0014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/f38084fa-35aa-780d-8434-39ba5e2f2284.png)
下記画面のようになれば、設定は完了です。
![0015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740235/cb27d7fd-6103-8d37-9bc0-e4598283448c.png)
<h1>最後に</h1>
結構簡単にできるので、機会があれば試してみてください。
[Nuxt3 / TS] ESバージョンの指定方法

Nuxt3で開発をしていて、Serverモジュール内(/server/api)でBigintをした扱う際に、以下のエラーが出ました。

> ERROR: Big integer literals are not available in the configured target environment ("es2019")

Bigintは es2020 から対応しているものらしく、TypeScriptのバージョンを変更する必要があるようです。

ServerモジュールはNuxt3内のNitroエンジンによって動いているため、Nitroエンジンに設定を渡す必要があります。
`nuxt.config.ts` で以下のように記述することで ESバージョンの指定をすることが可能です。

```typescript
export default defineNuxtConfig({
  // (もろもろの設定)
  nitro: {
    esbuild: {
      options: {
        // esnextも可
        target: 'es2020'
      }
    }
  }
}
```

短くなりましたが、本記事が役立てば幸いです!
😸Happy Hacking👻
map()メソッドを使って多次元配列から特定の値を抽出し新規配列を作成する

JavasriptくんをChatGPTくんと組んでなぐりあう修行記録

```javascript
const myFavList = [
  { id: 23, name: "moketaro", favs :[ { fruits: "Apple" }, { hoby: "reading" } ] },
  { id: 11, name: "mokeko", favs :[ { fruits: "lemon" } ] },
  { id: 65, name: "mokemasa", favs :[ { fruits: "orange" }, { hoby: "birdwatching" } ] },
  { id: 190, name: "mokena", favs :[ { fruits: "kiwi" }, { hoby: "travel" } ] },
]

let resFiltered = myFavList.map(({name, favs}) => ({
  name: name,
  fruits: favs.find(fav => fav.fruits)?.fruits
}));

console.log(resFiltered);
```

```結果
[{
  fruits: "Apple",
  name: "moketaro"
}, {
  fruits: "lemon",
  name: "mokeko"
}, {
  fruits: "orange",
  name: "mokemasa"
}, {
  fruits: "kiwi",
  name: "mokena"
}]
```

使われている構文
- map()メソッド
- 分割代入（destructuring）
- アロー関数
- オプショナルチェイニング演算子（?.）

らしい（ChatGPTくんのお世話になりっぱなし）（あとで調べる）
多次元配列においてfav.fruitsだけ抽出したかった。値が存在しない時undefinedを返す処理、たいせつ。
map()メソッド使ってるから元の配列は破壊されていない……はず。

もうちょっと学習が進めばこのコードを読んだだけで何をしているのかわかるのだとおもうけど、私はまだえっちらおっちら… ('ω')

あと「配列っていってるけどJSだと正確にはオブジェクトリテラル」とかの読み替えがまだちょっとわからないです。題名間違えてたら教えてください。

プライグラウンドサービスとしてJSFiddleを使っているんですが、JSだけRunしてconsole見たい。おすすめのものないですかね。
iPadで書いてるので、できればブラウザベースだと助かるくらい。
Jetpack Composeで相対位置での配置をしたい（ConstraintLayoutのbiasみたいなやつ）

# 概要
中央に置きたいだけならAlignment.Centerで良いのだが**ConstraintLayoutでいうところのこの辺と同じ様に相対位置で要素を配置したい**という課題について調べた際の備忘録です。
- layout_constraintVertical_bias
- layout_constraintHorizontal_bias

# 結論
`BiasAlignment`を使えば良い。
縦横ともに0fが中央になり、-1f〜1fの範囲内で指定する。

```kotlin
@Composable
fun BiasAlignmentSample() {
  Box(
    modifier = Modifier.fillMaxSize(),
    contentAlignment = BiasAlignment(
      horizontalBias = -0.8f,
      verticalBias = 0.7f
    )
  ) {
    Text("Sample")
  }
}

@Preview(
  showBackground = true,
  showSystemUi = true
)
@Composable
fun BiasAlignmentSamplePreview() {
  BiasAlignmentSample()
}
```

上記のようなコードだとプロット位置はこうなる。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68671/b254d5d2-53d9-793d-f940-60c84d30e2d2.png width=400>

x軸は負の数を指定すると中央より左に、正の数を指定すると中央よりも右になる。
y軸は負の数を指定すると中央より上に、正の数を指定すると中央よりも下になる。

# 余談
0,0が中央になるなら数直線をイメージしてしまうけど、y軸方向が逆になって気持ち悪い:thinking_face:
（ConstraintLayoutのbiasと同じ挙動ですね）

今回の記事にまとめるにあたり、普段何気なく使っていたAlignmentの実装を見てみたら全てこいつで定義されていた。

```kotlin
@Stable
fun interface Alignment {
    fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset


    @Stable
    fun interface Horizontal {
        fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int
    }

    @Stable
    fun interface Vertical {
        fun align(size: Int, space: Int): Int
    }

    companion object {
        // 2D Alignments.
        @Stable
        val TopStart: Alignment = BiasAlignment(-1f, -1f)
        @Stable
        val TopCenter: Alignment = BiasAlignment(0f, -1f)
        @Stable
        val TopEnd: Alignment = BiasAlignment(1f, -1f)
        @Stable
        val CenterStart: Alignment = BiasAlignment(-1f, 0f)
        @Stable
        val Center: Alignment = BiasAlignment(0f, 0f)
        @Stable
        val CenterEnd: Alignment = BiasAlignment(1f, 0f)
        @Stable
        val BottomStart: Alignment = BiasAlignment(-1f, 1f)
        @Stable
        val BottomCenter: Alignment = BiasAlignment(0f, 1f)
        @Stable
        val BottomEnd: Alignment = BiasAlignment(1f, 1f)

        // 1D Alignment.Verticals.
        @Stable
        val Top: Vertical = BiasAlignment.Vertical(-1f)
        @Stable
        val CenterVertically: Vertical = BiasAlignment.Vertical(0f)
        @Stable
        val Bottom: Vertical = BiasAlignment.Vertical(1f)

        // 1D Alignment.Horizontals.
        @Stable
        val Start: Horizontal = BiasAlignment.Horizontal(-1f)
        @Stable
        val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f)
        @Stable
        val End: Horizontal = BiasAlignment.Horizontal(1f)
    }
}
```

# 参考
https://stackoverflow.com/questions/74869485/how-to-set-boxcontentalignment-centervertically40downthepage-need-advanced-a
Excelワークシート関数: _takeRowsUntil -- 条件に合うまでの間の行を取得する、行の動的な取得

2024年5月12日

関数型言語のリスト処理にある ``takeUntil`` に似た関数

## _takeRowsUntil

``_最初の判定行`` を一行ずつ ``_判定命題`` に掛けて条件を満たす最初までの行数分だけ ``_開始の取得行`` から下の行を取得する。（一行ずつ見ていく（＝繰り返し処理）ために不動点コンビネータ ``_rec`` を内部的に使っている。）

```
=LET(
  _rec, LAMBDA(f, LET(g, LAMBDA(x, f(LAMBDA(v, LET(w, x(x), w(v))))), g(g))),

  _takeRowsUntil,
    LAMBDA(_開始の取得行,_最初の判定行,_判定命題,
      _rec(LAMBDA(_self, LAMBDA(_取得行数,
        IF(_判定命題(OFFSET(_最初の判定行,_取得行数,0,1,COLUMNS(_最初の判定行))),
          OFFSET(_開始の取得行,0,0,_取得行数,COLUMNS(_開始の取得行)),
          _self(_取得行数+1)
        )
      )))(0)
    ),

  _takeRowsUntil を使う数式をここに書く
)
```

## 使用例: 空行になるまでの行を全部取得する

行数が何行なのか事前に分からない場合とか、日々データが増えていくようなデータの場合に、これが欲しい。

この例では ``A1:D1`` が取得したい行の先頭で、判定には ``A1`` 行から始まる行だけを使っており、判定命題としては ``LAMBDA(_名前, _名前="")`` を指定している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759695/4d1e505b-5c2f-cc16-bd96-25a232e69a85.png)
【Flutter】画面タップでキーボードをしまう方法

# はじめに

TextFormFieldを実装した時、キーボードを開く処理は特に必要ありません。
ただ、画面のキーボード以外の部分を触った時に、キーボードをしまう処理は意図的に設定しないといけません。

とても簡単なので、真似してみてください。

# 開発環境

[Flutterバージョン]
3.16.1

[使用端末]
PC: Macbook Air(M1)

[開発ツール]
VSCode

# キーボードをしまう処理

対象とするWidgetの親要素に、GestureDetectorを置き、onTapパラメータとbehaviorパラメータに、以下のコードを渡します。

```dart
GestureDetector(
    onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
    behavior: HitTestBehavior.opaque,
    child: ~画面要素~
)
```


# コード全体

```dart
class Demo extends StatelessWidget {
  const Demo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Demo"),
      ),
      body: GestureDetector(
        // ここを追加 ===
        onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
        behavior: HitTestBehavior.opaque,
        // ============
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: Center(
            child: TextFormField(
              decoration: const InputDecoration(hintText: "テキストを入力してください。"),
            ),
          ),
        ),
      ),
    );
  }
```
【備忘録】.isEmpty()の話

以前投稿した記事で、String型のnullチェックは.isEmpty()を使えばいいということを書いたんですが、どうやらこのメソッド2つあるらしいのでその違いと注意点をまとめていこうと思います。

<h2>String.isEmptyとStringUtils.isEmpty</h2>
isEmptyメソッドには「String.isEmpty」と「StringUtils.isEmpty」があるそうです。

共通点としては、どちらも『空文字判定をしてくれる』という点でが挙げられます。

<h2>相違点</h2>
では、どういった点が異なっているのか。
答は『null判定をしてくれるか否か』という点にあります。

StringUtils.isEmptyは空文字の場合trueを返すのと同時に、<strong>nullの場合もtrueを返してくれます。

一方で、String.isEmptyは<strong>nullの場合はNullPointerExceptionが発生してしまいます。

この違いを明らかにしておかないとnullチェックの意味を成せないということになってしまいますね。

<h2>StringUtils.isEmptyの使い方</h2>
StringUtils.isEmptyを使用したい場合は「Apache Commons Lang」のライブラリをインストールして「org.apache.commons.lang3.StringUtils」をインポートする必要があるそうです。

プロジェクトにライブラリがインストールさえされていれば、あとはエディターで簡単にインポートできそうですね。

<h2>まとめ</h2>
今回は、以前まとめたnullのチェックを深めた内容でした。使い分けは、そのプロジェクトで色々状況が違うでしょうから一概には言えませんが、私が使用するのは大体StringUtils.isEmptyです。（空文字はNGでnullはOKという場面があまりないから。）

今までは無意識的に使っていましたが、今後は目的と機能を意識して実装していきたいと思います。
Github Copilotのモバイル版を使ってみた


# Github Copilot のモバイル版がリリース

Github Copilot のモバイル版がリリースされました．

https://github.blog/2024-05-07-github-copilot-chat-in-github-mobile/

mobile 版でも github copilot を使うには，github pro 以上のアカウントが必要です.

# 使い方

使い方は単純で，github モバイル版アプリを開いたら，右下の Copilot アイコンをタップするだけです．

# private のリポジトリは Enterprise 版が必要

> For organizations using GitHub Copilot Enterprise, developers can direct GitHub Copilot to their organization’s private repositories and ask questions including: “What does this code snippet mean?” or “how often was this function used in the project?”

公式の[リリースノート](https://github.blog/2024-05-07-github-copilot-chat-in-github-mobile/#customized-in-github-copilot-enterprise)を見ると，private のリポジトリを copilot で参照するには，Enterprise 版が必要と書いてありました．

# リポジトリの内容を参照できない

モバイル版でリポジトリの内容を参照してもらおうと思ったのですが，残念ながらできませんでした．

![Open-Sora-Plan](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/470df410-9da1-9ade-63be-1ff3401091ea.jpeg)

以上で参照したのは，[Open-Sora-Plan](https://github.com/PKU-YuanGroup/Open-Sora-Plan)という，OpenAI の Sora のような動画生成 AI を作成しようという公開リポジトリです．

https://github.com/PKU-YuanGroup/Open-Sora-Plan

:::note info
以前（5/12）にはリンクすら貼ってくれなかったので，ファイルの中身までは見れないのでとりあえずリンクを貼ったみたいな感じなんでしょうか

![Open-Sora-Plam-pre](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/b55aad94-b645-5ace-cb29-bc8efe82213d.jpeg)
:::

# 昔のリポジトリであれば参照できる

昔のリポジトリであれば参照できました．
これは，シンプルに github copilot の学習データに入っている情報だと思います．

![mern-starter](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/4fbea87b-2e1f-8f01-5add-6686b7576d54.jpeg)

参照したのは mern-starter という，MERN stack のスターターキットである公開リポジトリです．

https://github.com/Hashnode/mern-starter

最後に README のリンクをのしてくれて，クリックするとしっかりリンクに跳べたので，リンクの機能はちゃんと動いているようです．

# まとめ

とりあえず，通常のプログラミングの質問はできるようなので，プログラミング関連でちょっと聞きたい時には使えそうです．
あとは単純にメモのような感じで使うこともできますね．
どういうチャットをしたのかが履歴に残るのは，後から何を考えていたか思い出すので便利なので

自分のリポジトリをモバイル版でも参照できるようになって欲しいですね．
もちろん，enterprise 版を使っている人は，参照できるようになっていると思います．
enterprise になりましょうということでしょうか
Grafana で 複数クエリの結果を条件にしたアラートルールの作成手順

Grafana で Azure Monitor をデータソースとして使用し、特定の条件に基づくアラートを設定する方法を解説します。  
この例では、Kusto クエリ言語(KQL)を用いて、Azure のサインインログを分析し、アクセス成功率が過去 5 日間の平均の 85%未満に低下した場合にアラートを出す設定を行います。  

## 前提条件

- Grafana に Azure Monitor データソースが追加されていること。  
- Azure Monitor で Kusto クエリ言語(KQL)が利用可能であること。  

## ステップ 1: アラートルールの作成

1. Grafana のメニュー画面から、「Alerting」⇒「Alert rules」を選択します。
2. 「Create alert rule」を押します。

## ステップ 2: Azure Monitor データソースの設定

1. パネルのデータソースとして「Azure Monitor」を選択します。
2. 「Logs」タブを選択し、KQL を用いてサインインログのクエリを設定します。

## ステップ 3: クエリの作成

- **クエリ A (本日のアクセス成功数)**

  ```kql
  SigninLogs
      | where TimeGenerated >= startofday(now()) and TimeGenerated < endofday(now())
      | summarize successful_signins = countif(ResultType == 0)
  ```

- **クエリ B (本日のアクセス総数)**

  ```kql
  SigninLogs
      | where TimeGenerated >= startofday(now()) and TimeGenerated < endofday(now())
      | summarize signin_attempts = count()
  ```

- **クエリ C (過去 5 日間の平均アクセス成功数)**

  ```kql
    // 過去5日間のサインイン成功数と試行数を取得
    SigninLogs
    | where TimeGenerated >= startofday(now()) - 5d and TimeGenerated < startofday(now())
    | summarize successful_signins = countif(ResultType == 0)
  ```

- **クエリ D (過去 5 日間の平均アクセス総数)**

  ```kql
    // 過去5日間のサインイン成功数と試行数を取得
    SigninLogs
    | where TimeGenerated >= startofday(now()) - 5d and TimeGenerated < startofday(now())
    | summarize signin_attempts = count()
  ```

- **Expression E (本日のアクセス成功率)**
  クエリ A 結果をクエリ B 結果で割り、100 を掛ける。

  ```
  ${A} / ${B} * 100
  ```

- **Expression F (過去 5 日間の平均アクセス成功率の 85%)**
  クエリ C 結果をクエリ D 結果で割り、0.85 を掛けて、100 を掛ける。

  ```
  ${C} / ${D} * 0.85 * 100
  ```

- **Expression G (判断上の計算)**
  Expression E から、Expression F を引く。（アクセス成功率が過去 5 日間の平均の 85%未満に低下したのか）

  ```
  ${E} - ${F}
  ```

- **Expression H (アラート要否の判断)**
  最終的に下記をアラート要否の判断としたいので「Threshold」とする。
  Expression E から、Expression F を引いて、0 以上は正常。0 未満でアラートとする。

  ```
  ${G}「IS BELOW 0」
  ```

## ステップ 4: 評価期間と通知チャネルの設定

1. アラートの評価期間を「5m」や「10m」など、適切な間隔で設定します。
2. 「Notifications」セクションで通知チャネルを選択し、アラート発生時に通知されるように設定します。

## ステップ 5: アラートルールの保存

1. 全ての設定を確認し、右上の「Save」ボタンをクリックしてアラートルールを保存します。
プロジェクトマネージャ試験のすすめ

# プロジェクトマネージャ試験とは
プロジェクトマネジメント領域の知識・実践能力(スキル)が問われる
秋季に実施される情報処理技術者試験の高度レベル（レベル４）の論文試験。
求められる知識・スキルレベルはITSS 7段階中レベル4(中の中)　※専門家としてはｱﾀﾘﾏｴレベル

# なぜPM試験をおすすめするか
- 人気・評価が高い
- スペシャリスト系の試験より勉強時間が短くてすむ
- 問われる知識・スキルが実務での汎用性が高い

## 問われる知識・スキルが実務での汎用性が高い
### 問われる知識(プロジェクトマネジメント領域)の汎用性

プロジェクトの定義「独自性がある。有期的である。」
→ ルーティンワーク以外（非定型・非定例業務）は大体プロジェクトの定義に当てはまる
→ 大なり小なりプロジェクトマネジメントの知識が応用できる

× ：プロジェクトマネジメント領域の知識は、大規模ウォーターフォールプロジェクトのPMにとってのみ必要
〇：多くの業務にプロジェクトマネジメントの知識は応用可能


### 問われるスキルが実務に役立つ
高度情報論文資格（午後ⅠⅡ）では実務で役立つ考える力を問われる。（他の暗記系の資格対比）
→ 勉強を通じて考える力の向上が見込める

#### 午後Ⅰ
問われるスキル：理解力＋論理・水平思考
試験形式：長文を読解し、問われた内容に20～40字程度で答える

問われ方：「なぜ、こうしたのか？」「どのようなリスクが考えられるか」
長文から必要な情報を理解する力、なぜ？という問を深堀する論理思考・水平思考

開示されている情報から相手の言いたいことを理解する。リスクやメリットデメリットを提示することは、
普段の業務で必要とされる。

#### 午後Ⅱ
問われるスキル：説明力（相手にわかるように伝える）

試験形式：お題目が例示され、問に対して800字～1200字で論述する（３問）

問われ方・答え方：
「～について実施したことを論述せよ」
採点者（相手）に向けて問われた内容を説明する必要がある。
わかりやすいようにｱﾀﾘﾏｴレベルで整理する（例えばPREP法）
Point(要点・主張)：～のような対策を実施した。
Reason(理由)：なぜならば、～と考えたからである。
Example(例)：具体的には、～
※論文では重複は嫌われるので最後のPは省略

相手から求められている内容を、わかりやすい形式にまとめて、相手にわかるように伝える
これも普段の業務で必要とされる能力

# どんな人におすすめか
- 情報処理安全確保支援士試験合格済み
→ 応用情報・情報処理安全確保支援士が残っているならお先に

- スペシャリスト系試験を1年未合格
→ ネットワークスペシャリスト・データベーススペシャリストが残っていると手が出にくいが、2回分未受験から不合格ならいったん離れて論文試験に移った方が効率的かも

# 結論
秋季の情報処理技術者試験は積極的にPM試験を受けましょう

→ 勉強法などは次回に続く
【環境構築】Pythonの実行環境構築のベストプラクティス

- `python`の実行環境には`docker`を使用していたが、電力消費が多いのと接続クラッシュがしやすく悩んでいた。
- 仮想環境の構築が苦手だったが、一番良さそうな方法をLLMが教えてくれたのでメモ。


はい、以下の手順でHomebrewを使ってpyenvをインストールし、pyenvで仮想環境を作成して、VSCodeで使用できるようにする方法をまとめました。

1. Homebrewでpyenvをインストールする
   - ターミナルで以下のコマンドを実行 [1][2][4][10][13]
     ```
     brew install pyenv
     ```
   - シェルの設定ファイル（~/.bash_profileまたは~/.zshrc）に以下を追記 [1][3][4][13]
     ```
     export PYENV_ROOT="$HOME/.pyenv"
     export PATH="$PYENV_ROOT/bin:$PATH"
     eval "$(pyenv init -)"
     ```
   - 設定ファイルを再読み込み
     ```
     source ~/.bash_profile
     ```
     または
     ```
     source ~/.zshrc
     ```

2. pyenvを使って仮想環境を作成する
   - 使用可能なPythonのバージョンを確認 [1][3][11]
     ```
     pyenv install --list
     ```
   - 指定バージョンのPythonをインストール（例: 3.9.6） [1][3][11]
     ```
     pyenv install 3.9.6
     ```
   - プロジェクトディレクトリに移動し、ローカルでPythonのバージョンを指定 [3][11]
     ```
     cd /path/to/project
     pyenv local 3.9.6
     ```
   - 仮想環境を作成 [3][9][11]
     ```
     python -m venv venv
     ```

3. VSCodeで作成した仮想環境を認識して使用する
   - VSCodeでプロジェクトのディレクトリを開く [5][14]
   - コマンドパレットから "Python: Select Interpreter" を選択 [5][14]
   - 作成した仮想環境の Python インタープリター（./venv/bin/python）を選択 [5][14]
   - ターミナルを開くと、自動的に仮想環境がアクティベートされる [5][14]

以上の手順により、HomebrewでpyenvをインストールしてPythonのバージョンを管理し、プロジェクトごとに仮想環境を作成して、VSCodeでその仮想環境を使用することができます。仮想環境を使うことで、プロジェクトごとに依存パッケージを分離し、競合を避けることができます。

Citations:
[1] https://kredo.jp/media/mac-python-installation/
[2] https://zenn.dev/mook_jp/articles/1d915a0aef83a7
[3] https://zenn.dev/tigrebiz/articles/2822fb4de256d8
[4] https://www.codevace.com/install-python-on-mac/
[5] https://qiita.com/narista/items/087c9a89880edc67b570
[6] https://blog.deepblue-ts.co.jp/virtual_env/pyenv_poetry/
[7] https://logixsquare.com/techblog/visual-studio-code-python-version-settings/
[8] https://qiita.com/Ryo-0131/items/321ae71ec15f969cd43f
[9] https://camp.trainocate.co.jp/magazine/venv-python/
[10] https://qiita.com/nokonoko_1203/items/a694be4e76da0872f51a
[11] https://zenn.dev/ryotajin/articles/19-build-python-by-pyenv-venv
[12] https://nshalnote.com/?p=323
[13] https://www.rcnp.osaka-u.ac.jp/~yoshikaw/development/python.html
[14] https://qiita.com/youichi_io/items/bc9382fdef30ccdaf0bd
[15] https://takeg.hatenadiary.jp/entry/2021/05/22/165935
[16] https://flourish-group.com/blog/python-vatual-enviroment/
[17] https://qiita.com/yabish/items/93c4e043e4c8dbc60cad
[18] https://original-game.com/python_course/install/mac-homebrew-pyenv/
[19] https://zenn.dev/kenghaya/articles/9f07914156fab5
[20] https://tld.holy.jp/2022/12/07/install-python/
講師を務める人が学ぶべきバッドプラクティス

# なぜ講師向けの記事を書いたか？
どうもラクーンホールディングスのシュウヤです！
今年、私は事業部を含めた新卒向けの技術研修の総指揮と講師を務めました。技術についての記事は多くある一方で、技術者視点での研修を実施する際のコツについては情報が少ないため、役立てるかなと思い記事を書きました。

# この記事を読むと何が分かる？
- 講師側が「避けるべきこと」を学べる

# なぜバッドプラクティスなのか？
研修にはベストプラクティスはありませんが、バッドプラクティスは存在します。研修にベストプラクティスが存在しないのは、時と場所と人によってベストプラクティスが異なるからです。研修を実施する側(講師)も、受ける側(生徒)も、それぞれ異なる人間です。また、日や時間、体調によってもベストプラクティスは変わります。しかし、バッドプラクティスは存在します。バッドプラクティスの特に問題な点は、何も考えずに講師を務めようとすると勝手にバッドプラクティスになってしまう点です。なので、バッドプラクティスを学べば、最低限の質は担保できると考えました。

# 背景
## 目次
- これから講師を務める人が読むべきバッドプラクティス
    - 準備編
        - 研修の目的を理解せずに資料を作成する
        - 目的と手段が逆になった資料を作成する
        - 他研修とのつながりを無視して資料を作成する
        - 既存の資料を使いまわす

    - 本番編
        - 資料をすべて説明してからハンズオンを実施する
        - 講師が質問をせず一方向で説明をする
        - グループワークを実施しない
        - 休憩時間中雑談をしない

## 準備編
ここでは研修を実施するまでに必要な準備の時にしてはいけないことを学びます。重要度だけで言えば、準備編の方が本番編よりも重要です。準備編でバッドプラクティスを学び準備をすることである程度の品質が担保された研修資料が作りあがるでしょう。一見これらのバッドプラクティスは当たり前のことに見えます。しかし、いざ、研修を行おうとするとついやってしまったりしていますので注意しましょう。

### 研修の目的を理解せずに資料を作成する
全てのバッドプラクティスの中でこれが最もバッドでしょう。研修には必ず目的があるはずです。その目的を見失えば、ちぐはぐな資料が生まれます。生徒側からしても、なぜ学んでいるのかわからなくなりますこの研修が何を目標にしているのかわからず、生徒の意欲が下がるかもしれません。料理を例にとると「おなかを満たしたい」と「おいしいものが食べたい」では作る料理が変わってきます。これを理解しないと、どんなに品質の良いものでも満足度が下がります。すでに何の研修をやるか決まっている場合には、なぜそれが実施しているかについて確認をとったり考えることが必要です。

### 目的と手段が逆になった資料を作成する
これもよくありがちなバッドプラクティスです。自分たちができることから資料を作り始めてしまうということです。この結果として研修の目的を満たさない資料が出来上がります。例えば、自分が作れる料理にチャーハンがあったので、チャーハンを大量に作り客にふるまいます。しかし、客は少量で美味しい高級料理をあじわって食べたいと思っていました。これは満足度が下がりますし、チャーハンである必要はないでしょう。このように目的から手段を考えることが大切となってきます。

### 他研修とのつながりを無視して資料を作成する
研修の目的を理解してよし！資料を作成しよう！といきなり一人で資料を作成すると失敗します。研修は複数あることが常です。研修毎に教える内容が全く関係ない場合、研修を受ける側からすれば体系的に理解することは難しくなります。結果として本来の目的を達せない場合があります。ベルトコンベーア式で、一つの商品を作るときそれぞれの部品が意味を成して一つの商品を作ります。そうでなければ、商品はちぐはぐな商品となります。このように資料同士の関係性というのにも注意すべきです。

### 既存の資料を使いまわす
完璧な研修というのもは存在しません。状況によって最適な研修は変わるからです。例えば研修資料に猫ミームやジョージメンズコーチを入れたとします。今は流行っているので理解の促進に役立ちますが、これを知らない世代に向けて、当時流行っていたミームが研修資料を理解する助けとならず、むしろ認知的負荷が高くなってしまいます。

## 本番編
ここでは研修本番の時のバッドプラクティスについて学びます。生徒が見る場所はこの研修を実際に受けるときです。しっかりと学んでおくと良いかと思います。

### 資料をすべて説明してからハンズオンを実施する
誤解のないようにすべてを理解してもらってから実践してもらおうと考える人に陥りがちです。人間の短期記憶は7項目±2の情報を保持できると言われています。例えば、変数の扱い方を学ぶというのが目的とすれば、概念として変数とは何か、宣言とは何か、代入とは何かと、実際に書く上での宣言、代入などを含めての7±2となります。つまり、講師が一生懸命にすべてを説明した後にハンズオンを実施しても、生徒側は、ほぼ覚えていません。定期的にハンズオンを実施することが必要となるでしょう。

### 講師が質問をせず一方向で説明をする
資料を説明する時に全く生徒に質問をしない講師がいます。一方向だと生徒側にとっては集中力を欠き理解力が下がります。生徒側に講師が積極的に質問をすることで緊張感と集中力を維持して理解力の向上に充てることができるでしょう。

### グループワークを実施しない
グループワークを実施することは中々難しいでしょうが、絶対に必要だと思います。理解力の促進、責任感、コミュニケーションの向上などが挙げられます。役割分担をすることで緊張感と集中力が生まれます。これは理解力の向上を促します。また。生徒側が仕事は一人ではできないということを理解し、協調性やコミュニケーションを促進することが期待できます。

### 休憩時間中雑談をしない
集中力を高く保つために休憩時間をとる研修は多いと思います。他方で、休憩時間中に生徒側と講師側の雑談を必須だと考える人は少ないと感じます。しかし、休憩時間中の雑談は非常に大切です。生徒側が何を考えていて研修に対してどう思っているかを聞き出すことが出来ます。更に、生徒が講師へ信頼感を生むことも期待できます。講師の○○さんが言うんだから頑張るかなどモチベーションが下がっている生徒に対しても効果が期待できます。

## まとめ
いかがでしたでしょうか？単純な積み重ねのように思えるかもしれませんが、実は多くの落とし穴が存在し、研修を慎重に進める必要があることをご理解いただけたと思います。これが誰かの役に立てば幸いです。
なんで左辺に?.があると代入できないの？（半年前の俺へ）

## はじめに
VSCodeを使用していると、自動で?.(オプショナルチェーン)を付与してくれます。半年前の自分は「オプショナルチェーンでundefined(null)対応ができてるんだなー」というふわふわ認識だったので、この記事を贈ることにしました。

タイトルにある「左辺に?.があると代入できない」とはこういうことです。
```javascript
// 代入式の左辺には、省略可能なプロパティ アクセスを指定できません。ts(2779)
hoge?.property = 'fugafuga'
```

この式の意図は「hoge.property に 'fugafuga' を代入したい。」ですね。もっと付け加えると、「hoge.property に 'fugafuga' を代入したい。**ただし、hogeがundefinedかnullのときは何もしない**」です。
「オプショナルチェーンでundefined(null)対応ができてるんだなー」の認識だった自分はなんでこれで怒られてるのかわかりませんでした。

## 結論
~~hogeがnullもしくはundefinedのとき、左辺がまるごとundefinedとなるので、undefinedに代入をしてしまうことになるから。~~
↑記事を書いてるうちに「本当か？」となってしまった。とりあえずオプショナルチェーンに代入をしてはいけない「イメージ」として載せておく。

```javascript
// こんなことをしようとすることになる？
undefined = 'fugafuga'
```

## ?.（オプショナルチェーン）について
とりあえずMDN。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining


ざっくり、?.の左が undefined か null の場合はそこで終了してundefinedになってくれます。


```javascript
// id="hoge"の要素があれば hogeElement にその要素が入る。なかったらnullが入る
const hogeElement = document.getElementById('hoge')

hogeElement?.textContent
```
↑?.の箇所で**hogeElementがnull または undefinedかどうかのチェック**がされます（今回はundefinedの可能性はないですが）。
チェックの結果、hogeElementがnull または undefinedであれば「hogeElement?.textContent」はundefined となります。

## 左辺に?.を書くと

```javascript
const hogeElement = document.getElementById('hoge')

// 怒られる
hogeElement?.textContent = 'fugafuga'
```
↑もしこう書いたら、hogeElementがnullだった場合、**左辺はundefined**になります。
そのばあいundefinedに代入を試みていることになりそうです。
それは変なので、左辺にオプショナルチェーンはかけない、というイメージでいます。

## null や undefined でないときのみ代入したいときはどうするの
さて、この記事を書きはじた理由は「Null合体代入(??=)を使えば短くかけるのでは？」と思ったからです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_assignment

すなわち、「オプショナルチェーンによりundefinedと評価されなければ代入する」ができると思いました。
しかしながらこの書き方もエラーが出てしまいます。とにかく代入式の左辺にはオプショナルチェーンはかけないようです。
```javascript
const hogeElement = document.getElementById('hoge')

// 残念ながら怒られる
hogeElement?.textContent ??= 'fugafuga'
```

結局早期リターンするか
```javascript
if(!hogeElement) return
hogeElement.textContent = 'fugafuga'
```
&& を使用するのがいいのでしょうか
```javascript
hogeElement && (hogeElement.textContent = 'fugafuga')
```
いずれもhogeElementを2回書かないといけないのが引っかかります。

とはいったものの、今まで早期リターンで書いていて困ったことはないので、気長に探してみます
【フォームのアクセシビリティ】label要素を使用すると起きるうれしいこと

こんにちは。齋藤（[@wtoddev](https://twitter.com/wtoddev)）です。

今回は、最近業務でフォームのマークアップをする機会があり、改めて`label`要素の重要性を考えさせられたため、記事投稿キャンペーン「[アクセシビリティの知見を発信しよう！](https://qiita.com/official-events/4d9893df2bfd52211392)」に参加して備忘録を記したいと思います。

## そもそも`label`要素とは
`label`タグは、主にフォームの項目について、ユーザーに対して入力する内容を説明するキャプションを示すために使われるHTMLの要素です。

![スクリーンショット 2024-05-12 14.01.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919446/170f5df7-f9c7-6f5f-4d0f-2dce9199091d.png)

```html:使用例
<div>
    <input type="checkbox" id="agreement" name="agreement" />
    <label　for="agreement">利用規約に同意する</label>
</div>
```

`label`要素は通常、`input`や`textarea`などのフォーム要素と組み合わせて利用されます。

その際、`label`タグの`for`属性に`input`タグなどの`id`を指定すると紐づけができます。

## `label`タグを使用してマークアップすると何が良いのか
フォーム内の項目のキャプションを示すために`label`タグを使用すると、アクセシビリティの観点では以下のような利点があります。

### `input`要素などにフォーカスするとスクリーンリーダーがキャプションを読み上げてくれる
![スクリーンショット 2024-05-12 14.00.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919446/7c3c38e0-c159-519d-b832-079e91f0e044.png)

画像のような場合、キャプション部分を`label`タグを用いてマークアップし、`for`属性を用いて`input`要素などと紐づけることにより、チェックボックス部分にフォーカスすると、スクリーンリーダーが`label`要素に記述したキャプションを読み上げてくれます。

このことにより、視覚にハンディキャップのあるユーザーが入力項目を理解しやすくすることができます。

### クリック可能領域が拡大して入力しやすくなる
![スクリーンショット 2024-05-12 14.22.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919446/7fdf98a2-00e5-58c1-fd8e-26b20b701f60.png)

画像のような場合、`for`属性を使用して`input`要素と`label`要素を紐づけることにより、チェックボックス部分だけではなく、「利用規約に同意する」の部分もクリック可能領域になります。

このことにより、チェックボックスの操作をしやすくでき、特にタッチデバイスを使用する場合や、精密なマウス操作が難しい場合の利便性を向上させることが可能になります。

```math
ID = log_2(\frac{2D}{W})
```
目標が小さければ小さいほどユーザーはその目標への到達が困難になってしまう（フィッツの法則[^1]）ため、クリック可能領域を十分に確保することはユーザー体験の向上にも資することになります。

## さいごに
今回は、キホンのキかつn番煎じな内容ではありますが、フォームのマークアップをするうえで意識しておきたい　`label`要素についてお話しました。

フォームをマークアップする方の一助となれば幸いです。

[^1]: UIにおけるユーザーの動作をモデル化したもの。目標に到達する時間は、目標の大きさと近さに反比例するという法則（ID = 目標到達の困難さ / W = 動きの方向に測った目標の幅 / D = 開始点から目標の中心までの距離)
個人メモ： terraformer + terraform + AWS

※ 個人的なメモ
(事後なので抜けあるかも...)

# AWS現環境をterraformのコードで管理する

## 前提
- AWSリソース作成済み
- aws configure、terraform、terraformerの準備、インストールができている

## やること
- AWSの現環境をterraformerを使用してコード化
- コード化したterrafomerのコードをtfファイルを作成して、AWSリソースと紐づける
- terraformを使用してAWSリソースの変更をしてみる
- tfstateの管理場所をlocalからs3に変更する

## AWSの現環境をterraformerを使用してコード化
### AWSリソースをterraformerを使用してコード化する
- 下記はS3の例
```bash
$ terraformer import aws --resources=s3 --regions=ap-northeast-1 --profile=default
```

- 実行結果
![スクリーンショット 2024-05-12 14.04.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/032719cb-4338-d6d5-1cde-635dc8720925.png)
- generated/ にコードが生成される
```
.
├── README.md
├── generated
│   └── aws
│       └── s3
│           ├── outputs.tf
│           ├── provider.tf
│           ├── s3_bucket.tf
│           ├── s3_bucket_policy.tf
│           └── terraform.tfstate
```

---

### コード化したterrafomerのコードをtfファイルを作成して、AWSリソースと紐づける
- terrafomr importを使用して紐づける
    - ./s3.tfを作成して、./generated/aws/s3/s3_bucket.tfのコードを任意のリソースをコピーして貼り付ける
```
// tfファイルにこのように書かれている場合下記のように指定する (resource "aws_s3_bucket" "hoge" {...})
$ terraform import aws_s3_bucket.hoge {紐づけたいS3バケット名}
```

- 実行結果
![スクリーンショット 2024-05-12 14.27.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/68d9fbc8-6316-6769-4b25-e6cd5042684f.png)

- terraform plan で紐づいていることを確認
![スクリーンショット 2024-05-12 14.29.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/6e587d94-ea5f-2415-a3ff-9d6829af62b4.png)

![スクリーンショット 2024-05-12 14.33.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/4cae7e6d-03a6-c1e6-8a0d-241fdc3153f2.png)

---

### terraformを使用してAWSリソースの変更をしてみる
- 適当にコードを編集
```terraform
// false→trueに変更
force_destroy = "true"
```

- terraform planで差分確認
```bash
$ terraform plan
```
![スクリーンショット 2024-05-12 14.39.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/eda5d898-c2d6-454f-dcb0-f8dddbebcbde.png)

- terraform applyで差分を反映、反映前に差分確認が入るので `yes` と打つ
```bash
$ terraform apply
```
![スクリーンショット 2024-05-12 14.43.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/75cec120-48df-1ae3-97ce-59887ff3878a.png)

- 差分が反映される
![スクリーンショット 2024-05-12 14.46.16 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/e2c0b683-8eb5-3f96-9f5d-a9247f6cfac4.png)

---

### tfstateの管理場所をlocalからs3に変更する
- main.tfに下記を追記
```terraform
terraform {
  backend "s3" {
    bucket                  = "matsui-backend-tfstate" // tfstateを管理するバケット名
    key                     = "terraform.tfstate" // tfstateのファイル名
    region                  = "ap-northeast-1"
  }
}
```

- その後、terraform initを実行し、localに配置しているtfstateをS3にコピーするか聞かれるので `yes` と打つ
```terraform
$ terraform init
```
![スクリーンショット 2024-05-12 14.58.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1260517/20b088e3-b674-518d-26cd-70d43a47dc05.png)
SSH接続

#   Linuxで公開鍵認証をする方法

## SSHを使った公開鍵認証の手順
 
#### ステップ１　SSHの秘密鍵と公開鍵を生成
sshキー作成コマンド
```
[root@localhost ~]# ssh-keygen　
```


ホームディレクト配下に隠しファイル.sshが作成されていることを確認する
```
[root@localhost ~]# ls -la
drwx------   2 root root   38  5月 12 13:35 .ssh

```

### .sshファイルへ移動し公開鍵と秘密鍵を確認し、公開鍵のファイル名を変更する

```
[root@localhost ~]# cd .ssh
[root@localhost .ssh]# ls
id_rsa  id_rsa.pub）
[root@localhost .ssh]# mv id_rsa.pub authorized_keys
[root@localhost .ssh]# ls
authorized_keys  id_rsa
```

### 秘密鍵をクライアント側へコピーor移動した後にサーバー上から削除する
※コピー方法1teratermのファイル(F)
![スクリーンショット 2024-05-12 135327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3753488/80dba177-6a5d-33d3-72ff-8a91a053bf98.png)

SSH SCPをクリック
次に移動したいファイル名の絶対パスを記入
![スクリーンショット 2024-05-12 135556.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3753488/4c4dd57a-09c2-bea3-fb20-8305bbba02b1.png)

コピー方法2
cat id_rsaで秘密鍵をコピーする方法もある

秘密鍵の削除
```
[root@localhost .ssh]# rm -f id_rsa
[root@localhost .ssh]# ls
authorized_keys
```

### 公開鍵のパーミッションの変更
作成ユーザ以外の権限削除

```
[root@localhost .ssh]# chmod 600 authorized_keys
[root@localhost .ssh]# ls -l
合計 4
-rw------- 1 root root 580  5月 12 13:35 authorized_keys
[root@localhost .ssh]# chmod 700 ../.ssh
```
# サーバ側(192.168.40.81)の設定は以上


次はクライアント側(192.168.40.128)から秘密鍵を使ってログインする手順
### 先ほど作成したデスクトップ上の秘密鍵をクライアント側のteratermにドラッグアンドドロップ

カレントディレクトリに移動できたことを確認
```
[root@localhost ~]# ls
 id_rsa  
[root@localhost ~]#
```

### 最後にid_rsaの鍵のパーミッションを変更
```
[root@localhost ~]# chmod 600 id_rsa
[root@localhost ~]# ssh -i id_rsa root@192.168.40.81
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Sun May 12 14:43:41 2024 from 192.168.56.3
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
[root@localhost ~]#
```
成功