OmniAICreator/Qiita-1.07M huggingface dataset:
Karateでシークレット情報を扱う

# はじめに
APIテストではAPIキーやトークンなどの機密性の高いシークレット情報を使うケースが多々あります。
そこで今回はKarateでのシークレット情報の取り扱い方に触れてみたいと思います。
# 注意点
Karateが公開しているテンプレートでは[Logback](https://github.com/karatelabs/karate-template/blob/main/src/test/java/logback-test.xml)が使われており、テスト実行時のリクエスト/レスポンス内容がログファイルやテスト結果レポートに出力される場合があります。
また、テストスクリプトを記述するfeatureファイルや実行時の設定を記述するkarate-config.jsでは任意の内容をログ出力する処理を記述することもできます。
もし、その中にシークレット情報を使ったテストがあった場合、特に対策せずにテスト実行をするとセキュア情報がログファイルなどにそのまま出力されてしまいます。
# 対策
Karateの[HttpLogModifier](https://github.com/karatelabs/karate/blob/master/karate-core/src/main/java/com/intuit/karate/http/HttpLogModifier.java)の実装クラスを作成し、セキュア情報のマスキングを行います。

### 実装クラスの作成
以下はKarateが公開している[実装例](https://karatelabs.github.io/karate/karate-demo/src/test/java/demo/headers/DemoLogModifier.java)です。
このheaderメソッドでは、リクエストヘッダーに”xss-protection”が含まれる情報がログ出力される際に”***”に変換するという処理が記述されています。
この実装例を参考に必要な箇所・必要な情報に対してマスキング処理を実装してください。
```DemoLogModifier.java
package demo.headers;

import com.intuit.karate.http.HttpLogModifier;

/**
 *
 * @author pthomas3
 */
public class DemoLogModifier implements HttpLogModifier {
    
    public static final HttpLogModifier INSTANCE = new DemoLogModifier();

    @Override
    public boolean enableForUri(String uri) {
        return uri.contains("/headers");
    }

    @Override
    public String uri(String uri) {
        return uri;
    }        

    @Override
    public String header(String header, String value) {
        if (header.toLowerCase().contains("xss-protection")) {
            return "***";
        }
        return value;
    }

    @Override
    public String request(String uri, String request) {
        return request;
    }

    @Override
    public String response(String uri, String response) {
        // you can use a regex and find and replace if needed
        return "***";
    }

}
```
### 実装クラスの適用
次に、HttpLogModifierの実装クラスが動作するように設定します。
+ テストスクリプト毎に個別の設定をしたい場合
対象のfeatureファイルにHttpLogModifierの実装クラスのインスタンスを作成する処理を記述してください。
```.feature
* def LM = Java.type('demo.headers.DemoLogModifier')
* configure logModifier = new LM()
```
+ 全体に設定したい場合
karate-config.jsにHttpLogModifierの実装クラスのインスタンスを作成する処理を記述してください。
```karate-config.js
var LM = Java.type('demo.headers.DemoLogModifier');
karate.configure('logModifier', new LM());
```
この様な処理を実装することでKarateで安全にシークレット情報を取り扱ってAPIテストを実行することができます。
@uzulla さんの「一般社団法人サイバー技術・インターネット自由研究会の電子公告をPHPで読む」にダメ出しする

# 元ネタ

https://zenn.dev/uzulla/articles/1e344dfbf45035

# コード

```php:Before
<?php

$fh = fsockopen("koukoku.shadan.open.ad.jp", 23, $ec, $em);

while (!feof($fh)) {
    $chunk = fread($fh, 2);
    echo mb_convert_encoding($chunk, 'utf-8', 'sjis');
}
```

```php:After (fread を使う一般的な解答)
<?php

if (!$sock = stream_socket_client('tcp://koukoku.shadan.open.ad.jp:23')) {
    exit(1);
}
if (!stream_filter_append($sock, 'convert.iconv.cp932/utf-8')) {
    exit(1);
}

while ('' !== $byte = (string)fread($sock, 1)) {
    echo $byte;
}
```

`fread` で書いたあとに `fgetc` でいいじゃんってことに気づいたので↓を追記

```php:After (fgetc を使う別解)
<?php

if (!$sock = stream_socket_client('tcp://koukoku.shadan.open.ad.jp:23')) {
    exit(1);
}
if (!stream_filter_append($sock, 'convert.iconv.cp932/utf-8')) {
    exit(1);
}

while (false !== $char = fgetc($sock)) {
    echo $char;
}
```

# 何を変えたか

## 重要なところ

### `fsockopen` は古い

https://www.php.net/manual/ja/function.fsockopen.php

https://www.php.net/manual/ja/function.stream-socket-client.php

PHP 5 以降では `stream_socket_client` だけで全て要件は満たせるはず！
<font color=silver>なお私の PHP デビューは 5.2 ですが普通に昔 `fsockopen` 使ってました（小声）</font>

### `feof` の判定は無限ループになる可能性がある

- `feof` が `true` を返す条件
  - EOF への到達 
- `feof` が `false` を返す条件
  - まだ有効なデータがある
  - <font color=red>**エラー**</font>

というわけで，**何かあったときにこのスクリプトは<font color=red>無限ループ</font>になってしまう可能性があります**。 `fread` の返り値を見るほうが信頼性は高いでしょう。

### ストリームフィルタを使おう

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25060/84727047-9fc9-68d8-0c56-dd0278987b23.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25060/2a077e14-e0cf-edc2-7707-3aec92e056ee.png)

ストリームフィルタを使うと， `mb_convert_encoding` で中途半端なバイト列に変換処理を適用してしまって文字化けすることもないと思います。

## その他こだわり

- （ストリームフィルタを使う前提であれば） `fread` は 1 バイト単位でよくね？
- `fpassthru` とか `stream_copy_to_stream` で綺麗に書きたかったけど，内部でバッファリングされすぎて出力遅れちゃうのが微妙でした。でもファイルに書き出すならこっちのほうがいいと思う
- **`fread` は異常時以外 `false` は返さず，終了判定は空文字列との比較になる**点に注意。いっそのこと， **`false` が `string` キャストされると空文字列になる** 性質を生かして空文字列との比較に一本化すると綺麗に書けるでしょう。
  - よく似た関数の `fgets` は最後に `false` を正常系で返してくるのでハマりポイントの 1 つ。一方で `fgetc` は `fgets` と同じ挙動なので `false` との比較で OK
FirebaseをiOSアプリに追加する

# 実施前提
Podファイルを使った手順
Xcodeでxcworkspaceファイル(無い場合xcodeprojファイル)が開けること

・Github管理の場合
Githubからアプリをクローンして、ブランチ作成してチェックアウト

# Firebase組み込み手順
公式↓にアクセスして「使ってみる」
https://firebase.google.com/?hl=ja 

①「iOS」で設定開始

②「AppleアプリへのFirebaseの追加」
- アプリの登録
- バンドルID(Xcode Signing&CapablilitiesのBundleIdentifier)を登録

③ GoogleService-Info.plist をダウンロード
　ダウンロードしたGoogleService-Info.plistを以下の通り格納
　・xcworkspaceファイル/xcodeprojファイルがある階層でディレクトリを作成(名前は任意)
　・作成したディレクトリの配下にダウンロードしたGoogleService-Info.plistを格納
　・TargetやSTG/PRDで識別できるよう名前を変更(ex: Staging-GoogleService-Info.plistなど)

④ Podファイルの編集
　※無い場合はpod initで作成
　iOSバージョンはXcodeバージョンに従って設定(ex: platform :ios, '12.0')
　Podファイル各Targetに下記追記
```
pod 'Firebase/Analytics'
pod 'Firebase/Crashlytics'
pod 'Firebase/Performance'
```
⑤ Pod install
　※xcworkspaceが無い場合、Pod installで作成される為、Xcodeをxcworkspaceで開き直す
　※pod installのログに下記のような文が出る場合、次の手順の対象となるのでターミナルは閉じずにおくこと
```
[!]The `AppName [Release]` target overrides the `GCC_PREPROCESSOR_DEFINITIONS` build setting defined in `Pods/Target Support Files/Pods-AppName/Pods-AppName.release.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
```

⑥ Xcodeで各TargetのBuildSettingを開く
　下記に$(inherited)を追加
　・Linking -> Other Linker Flags
　・Framework Search Paths
　・HEADER_SEARCH_PATH
　・LIBRARY_SEARCH_PATH

⑦ User DeniedにPlistファイルの追加先を作成
　③で設定したPlistファイルの名前をそれぞれ指定

⑧ XcodeでTargetのBuild Phaseを開く
　Editor＞Add Build Phase＞Add Run Script Build Phase
　Copy GoogleService-Info.plistを作成して、Shellに下記を追加
```
GOOGLE_SERVICE_INFO_PLIST_FROM="${PROJECT_DIR}/FirebaseConfiguration/${GOOGLE_SERVICE_INFO_PLIST_NAME}.plist"
BUILD_APP_DIR="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}"
GOOGLE_SERVICE_INFO_PLIST_TO="${BUILD_APP_DIR}/GoogleService-Info.plist"
cp "${GOOGLE_SERVICE_INFO_PLIST_FROM}" "${GOOGLE_SERVICE_INFO_PLIST_TO}"
```
![スクリーンショット 2023-09-05 15.29.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2027418/109b42a8-0fe7-e670-fd96-dceec3b63e7a.png)


⑨ BuildPhaseでdSYMファイルを自動的にアップロードするように設定する
　下記のステップ２の通り実行(dSYMアップロードのスクリプト名ex: Upload Crashlytics dSYMs files)
　
https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=0&hl=ja#set-up-dsym-uploading
　※サイト内のスクリプトが変更されました→旧スクリプトでは${PODS_ROOT}/FirebaseCrashlytics/run
![スクリーンショット 2023-09-05 15.34.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2027418/358ca740-9896-3bbf-8aed-cc450a72cdc0.png)

⑩ 各TargetのProduct＞Scheme＞Edit Scheme＞Run＞Argumentsに下記を追加
　-FIRAnalyticsDebugEnabled
　-FIRDebugEnabled

11.　UIApplicationDelegateに初期化コードを追加

https://firebase.google.com/docs/ios/setup?authuser=0&hl=ja#initialize-firebase

12.　Firebase Crashlyticsを開始する場合、下記のコードを追記してクラッシュするかテストする
https://firebase.google.com/docs/crashlytics/get-started?hl=ja&platform=ios#force-test-crash

手順11まででビルドが成功したら完了！
Firebaseで作成したプロジェクトのアクセス状況などを確認する。
Laravel10のプロジェクトをローカル環境に作成するまでの手順

【個人用メモ】
ローカル環境でLaravelのプロジェクトを新規作成するまでの手順を以下に記載していく。

## 前提
- 「Laravel Herd」をインストールしていること
    - インストール方法は下記を参考
        - https://qiita.com/wadakatu/items/4a1dc12f4dd7a515a01b

## 手順1. 新規プロジェクトの格納先に移動
今回は「ドキュメント」配下に新規プロジェクトを作成する
```
cd ~/Documents
```

## 手順2. composerを用いてプロジェクトを作成
移動したディレクトリで以下のコマンドを実行
『{プロジェクト名}』には、任意のプロジェクト名を入力
```
composer create-project laravel/laravel {プロジェクト名} "10.*" --prefer-dist
```

例えば「example-app」のプロジェクト名としたい場合は
```
composer create-project laravel/laravel example-app "10.*" --prefer-dist
```
とする

## 手順3. 作成したプロジェクトを起動して動作確認
手順2で作成したプロジェクトのディレクトリに移動
```
cd {プロジェクト名}
```

「example-app」でプロジェクトを作成した場合は
```
cd example-app
```

LaravelのArtisan開発サーバを起動
```
php artisan serve
```
上記のコマンドを実行することで、Webブラウザにて`http://localhost:8000`からアプリケーションにアクセスできるようになる

下記のページが表示されたら成功
![スクリーンショット 2023-09-05 16.43.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123079/9333909b-6fa2-9e29-8288-20959e28bd71.png)
JavaScriptだけ（ライブラリなし）でオフキャンバスドロワー

### ライブラリなし、素のJavaScriptでもオフキャンバスドロワーが作れます。

💡ポイントは以下のように「JSからスタイルを指定」すること。

❌「JSでクラスを付け替えてCSSでスタイル変更」
　ではうまくアニメーションしませんでした。


```javascript:drawer.js

	// メニューを開く
	function openMenu() {
		// アイコン変形、ナビエリアvisible
		hamburger.classList.add(CLASS);
		menu.classList.add(CLASS);

		// ヘッダーを左へ移動
		header.style.transform = "translateX(-300px)";
		header.style.transition = "all 0.3s ease-in-out";

		// コンテンツ部分を左へ移動
		contents.style.transform = "translateX(-300px)";
		contents.style.transition = "all 0.3s ease-in-out";

		// マスクON
		headerMask.classList.add(maskOn);
		contentsMask.classList.add(maskOn);

		// 背面コンテンツ固定
		backgroundFix(true);
		hamburger.setAttribute("aria-expanded", "true");
		flg = true;
	}

```




<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🌻ライブラリなし！<br>　オフキャンバスドロワー🌻<br><br>素のJSでもオフキャンバスドロワーが作れます！<br><br>💡ポイントは次ポストの画像のように<br>　「JSからスタイルを指定」すること<br><br>❌「JSでクラスを付け替えてCSSでスタイル変更」<br>　ではうまくアニメーションしません<a href="https://twitter.com/hashtag/javascript?src=hash&amp;ref_src=twsrc%5Etfw">#javascript</a> <a href="https://twitter.com/hashtag/CSS?src=hash&amp;ref_src=twsrc%5Etfw">#CSS</a> <a href="https://twitter.com/hashtag/%E3%83%89%E3%83%AD%E3%83%AF%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#ドロワー</a> <a href="https://t.co/Mhlluv8Nab">pic.twitter.com/Mhlluv8Nab</a></p>&mdash; とも@Web制作ママ (@tomowillbe) <a href="https://twitter.com/tomowillbe/status/1698952732286353912?ref_src=twsrc%5Etfw">September 5, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
データ分析チームのロールとミッションについて

作った資料を忘れないように。チームの運営を守るために。（某会社のロール参考）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466674/838194b9-1c5f-19ca-d6ed-405579e032fe.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466674/eef28660-0155-1d13-cb59-0a09965c97a9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466674/77b9cad2-dfff-7daa-9211-fe61ec31987f.png)
CLion + NucleoF303K + openOCDでデバッグする話

brewで入れたopneOCDに付属しているnucleo用のコンフィグファイルだと、プログラムのダウンロードに失敗します。

結果

![スクリーンショット 2023-09-05 15.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/183fc3ae-ab9e-c231-b07a-217659a7fa33.png)

どうもst_nucleo_f3.cfgの中身を見ると NUCLEO F334R8 用のようで、F303K8用ではないようです。

そこでCubeIDEで、デバッガとしてOpneOCDを選択したとき生成される"プロジェクト名 Debug.cfg"というファイルを持ってきます。CubeIDEのプロジェクトルートにできますので、自分のディレクトにリネームして突っ込んでおくか、Gitで管理するならプロジェクトのルートにコピーしておきます。

![スクリーンショット 2023-09-05 16.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/f7b0131e-a18f-3a7f-265e-ce0522d55c96.png)

めでたくブレークポイントで止まっています。


違いは何かというと、openOCDについているものは

```tcl:/usr/local/Cellar/open-ocd/0.12.0_1/share/openocd/scripts/board/st_nucleo_f3.cfg
# SPDX-License-Identifier: GPL-2.0-or-later

# This is an ST NUCLEO F334R8 board with a single STM32F334R8T6 chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260004

source [find interface/stlink.cfg]

transport select hla_swd

source [find target/stm32f3x.cfg]

reset_config srst_only

```


一方CubeIDEが生成しているものは
```tcl:'プロジェクト名 'Debug.cfg
# This is an NUCLEO-F303K8 board with a single STM32F303K8Tx chip
#
# Generated by STM32CubeIDE
# Take care that such file, as generated, may be overridden without any 
# early notice. Please have a look to debug launch configuration setup(s)

source [find interface/stlink-dap.cfg]

set WORKAREASIZE 0x1000
transport select "dapdirect_swd"
set CHIPNAME STM32F303K8Tx
set BOARDNAME NUCLEO-F303K8

# Enable debug when in low power modes
set ENABLE_LOW_POWER 1

# Stop Watchdog counters when halt
set STOP_WATCHDOG 1

# STlink Debug clock frequency
set CLOCK_FREQ 8000

# Reset configuration
# use hardware reset, connect under reset
# connect_assert_srst needed if low power mode application running (WFI...)
reset_config srst_only srst_nogate connect_assert_srst
set CONNECT_UNDER_RESET 1
set CORE_RESET 0

# ACCESS PORT NUMBER
set AP_NUM 0
# GDB PORT
set GDB_PORT 3333

# BCTM CPU variables
source [find target/stm32f3x.cfg]
```

と色々設定しています。

stlink-dap.cfgをstlink.cfgとしても動きます。
色々コメントアウトしてみたところ、

set WORKAREASIZE 0x1000

という所が効いているようです。


F303K8用のcfgファイルも用意しておいて頂けると助かるんですが。。。

ということで、うんと簡素化すると

```tcl:'st_nucleo_f303k8.cfg
# For NUCLEO F303K8

source [find interface/stlink.cfg]
set WORKAREASIZE 0x1000
source [find target/stm32f3x.cfg]

```

で動いています(WDTはプログラムの中で無効化してます）。
stlink.cfgの中にはST_LinkのUSBのVID, PIDの組が
列挙されていますが、strageあり・なし両方のPIDが書かれているので
どちらでもデバッガとしては問題なく動作します。

他のNucleoボードもこれでいけるのでは。
Linuxディスク容量不足確認コマンド

# はじめに
Linux容量系の調査コマンドを整理しました。

```タイトル:Linux
#現在のディスク容量を確認
$ df -h <ディレクトリパス>
```

```タイトル:Linux
#サイズの大きいファイルを抽出
$ du -ah <ディレクトリパス> | sort -hr | head -<表示個数>

➡特定のディレクトリを除外する場合は「grep -v」をパイプに挟む
```

```タイトル:Linux
#長時間更新がないファイルを抽出する
$ find <ディレクトリパス> -mtime +日数 -size +<サイズ> -type f | xargs ls -hl

➡特定のディレクトリを除外する場合は「grep -v」をパイプに挟む
```
Rust the book 要約 １９章 ー４節：高度な機能 ー 関数とクロージャについての発展的な事項

## 目次

  - [19.4.0 関数とクロージャについての発展的な事項についての概要](#1940-関数とクロージャについての発展的な事項についての概要)
  - [19.4.1 関数ポインタ](#1941-関数ポインタ)
    - [関数ポインタを Enum と組み合わせる](#関数ポインタを-enum-と組み合わせる)
  - [19.4.2 クロージャを返却する関数](#1942-クロージャを返却する関数)

## 19.4.0 関数とクロージャについての発展的な事項についての概要

- 関数ポインタ
  - 関数を引数にとる関数を定義することができる
  - このとき、引数の型には `fn` を指定する
  - `fn` は関数ポインタと呼ばれる
  - `fn` はすべてのクロージャトレイト `Fn`, `FnMut`, `FnOnce` を実装している
    - &rarr; クロージャを引数にとる関数・メソッドには常に関数を渡すことができる
  - Enum と関数クロージャを組み合わせる書き方もあるので注意すること
  - 関数ポインタ `fn` は関数の戻り値の型に使うことはできないので注意

- クロージャを返却する関数
  - クロージャを返却する関数を記述する際は、クロージャトレイトのトレイトオブジェクトを返却する関数として実装すること

## 19.4.1 関数ポインタ

- クロージャだけでなく、通常の関数も関数に渡すことができる
  - これは、定義済みの関数を関数に渡したいときに便利（既存の関数をクロージャとして定義しなおす必要がない）

- 関数は**関数ポインタ** `fn` 型に型強制される
  - クロージャを表す型 `Fn` と混同しないように注意
  - `fn` は型、`Fn` はトレイト

- 例：

  ```rust
  // 普通の関数
  fn add_one(x: i32) -> i32 {
      x + 1
  }

  // 関数を引数にとる関数
  // 引数にとった関数を二回実行し、それらの結果を足して返す
  fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
      f(arg) + f(arg)
  }

  fn main() {
      // 関数を引数にとる関数を実行
      let answer = do_twice(add_one, 5);

      println!("The answer is: {}", answer);  // The answer is: 12
  }
  ```

- 関数型 `fn` はすべてのクロージャトレイト（`Fn`, `FnMut`, `FunOnce`）を実装している
  - つまり、クロージャを受け取る関数の引数に対しては常に関数を渡すことができる
  - なので、"関数的なもの"を受け取る関数を実装する際は、適当なトレイト境界を用いてクロージャを受け取る関数を書いて、クロージャと関数のどちらも受け取れるようにするのがベスト

- ただし、クロージャではなく `fn` だけを受けとるような関数を実装したくなる場合もある
  - 最たる例は、クロージャを持たない外部コードとのインターフェイス
    - たとえば、C言語の関数は関数を引数として受け取ることができるが、C言語にはクロージャがない

- インラインのクロージャも名前付き関数も使うことのできる場合の例：以下のコードは、さらにその下のコードと等価である

  ```rust
  // 数値のベクタを文字列のベクタに変換する例
  let list_of_numbers = vec![1, 2, 3];
  let list_of_strings: Vec<String> =
      list_of_numbers.iter().map(|i| i.to_string()).collect();
  ```

  ```rust
  // to_string 関数は複数あるので、引数に渡す関数はフルパス記法で指定する必要があることに注意
  let list_of_numbers = vec![1, 2, 3];
  let list_of_strings: Vec<String> =
      list_of_numbers.iter().map(ToString::to_string).collect();
  ```

### 関数ポインタを Enum と組み合わせる

- 例えば、以下のような Enum を考える

  ```rust
  enum Status {
    Value(u32),
    stop,
  }
  ```

- このとき、`Status::Value` の値は以下のように初期化できる

```rust
let status = Status::Value(1);
```

- これは、`Status::Value` が `Status` 型の初期化関数になることを表す

- この初期化関数も関数ポインタとして使用できる
- 例：

  ```rust
  let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
  ```

## 19.4.2 クロージャを返却する関数

- クロージャはトレイトによって表現されるので、クロージャを直接関数の返り値の型には指定できない

- 関数からトレイトを返却したいとき、多くの場合、代わりにそのトレイトを実装する型を関数の返り値の型に指定することで対応できる

- しかし、この方策はクロージャに対しては有効ではない
  - なぜならば、クロージャを実装する返却可能な具体的な型がないから
    - なお、クロージャトレイトを実装する `fn` は、返り値の型として使うことが許容されていない

- クロージャを返却する関数を実装したい場合は、トレイトオブジェクトを使用すること

- 例：

  ```rust
  fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
      Box::new(|x| x + 1)
  }
  ```

- 上記のコードで `Box` を使わずにそのまま `Fn(i32) -> i32` を返そうとすると、`Sized` トレイト関連のコンパイルエラーが発生する
  - これは、トレイトが動的サイズ決定型だからである
  - 19.3 節で述べたように動的サイズ決定型を使用する際は、ポインタと組み合わせる必要がある


## 参考文献

- [The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch19-05-advanced-functions-and-closures.html)
PCA, SVD, Lanczosアルゴリズムの関連性について調査したので備忘録

# Principal Component Analysis (PCA)、Singular Value Decomposition (SVD)、およびLanczosアルゴリズム

## 概要
Lanczos アルゴリズムについて調べる際に、固有値ベクトルなどを計算するための行列の低ランクへの分解である、
ということを知りました。

その時にいろいろな手法を比べてプログラムで動作を確認しました。

https://qiita.com/kmr-ergotic/items/542be90865dfcf346125

このときに、
SVDも行列の分解であったなあと思い出し、さらに、
低ランクという文脈では、次元削減であるPCAを思い出しますよね。

次元削減ではよく聞くPCA、SVD、
また、Lanczosアルゴリズムについてどのような関連性を持って理解しておけば良いのか混乱したため、
調べたことをいかに備忘録としてまとめておこうと思います。

調べていくと、やはり
PCA（主成分分析）、SVD（特異値分解）、およびLanczosアルゴリズムは、
線形代数と次元削減の文脈で関連しています。
ここでは、これらの関連性について説明します。


## 忙しい人のためのまとめ
### PCA（主成分分析）
- PCAとは何か
- PCAの数学的背後にあるSVDの関連性

### SVD（特異値分解）
- SVDの概要
- SVDとPCAの関係

### Lanczosアルゴリズム
- Lanczosアルゴリズムの特徴
- Lanczosアルゴリズムを使用したPCA


## 内容

#### PCAとは何か
PCAはデータの次元削減とデータ圧縮に使用され、データセットの最大分散を捉える直交ベクトルである主成分を特定します。
具体的には、PCAは共分散行列を固有値分解することで固有ベクトルを計算し、固有ベクトルをもともとの次元数より小さく選んで線形変換をすれば、次元削減ができます。

https://qiita.com/horiem/items/71380db4b659fb9307b4

この記事が非常にわかりやすかったです。


####  PCAの数学的背後にあるSVDの関連性

PCAはSVDの特殊なケースと見なすことができ、
データ行列Xに対してPCAを実行すると、Xの共分散行列の固有ベクトル（主成分）を見つけていることになりますが、この固有値とSVDの特異値の間には関係式があります。
これも上の記事にまとめられていました。

#### SVDの概要
SVDは行列を他の3つの行列に分解するための因子分解法であり、行列Aが与えられた場合、SVDはそれをA = UΣV^Tと表します。
UとVは直交行列で、Σは対角行列であり、その対角線上に特異値があります。

#### SVDとPCAの関係
特異値とUとVの対応する列は、行列A^TA（ここでA^TはAの転置です）の固有値と固有ベクトルと密接に関連しており、これによりデータ行列X上でSVDを実行してPCAを計算できます。

https://qiita.com/ImnotTakzoKadno/items/5e0705f96152206a886c

こちらに詳しい手順が載っていますが、
PCAとの違いは、固有値や固有ベクトルを求める対象が、
共分散行列か、もしくはX^TX に対してか、の違いですね。

#### Lanczosアルゴリズムの特徴
Lanczosアルゴリズムは、大規模な対称行列の極端な固有値とそれらに対応する固有ベクトルをいくつか見つけるための反復的な数値方法です。


#### Lanczosアルゴリズムを使用したPCA
PCAの文脈で、大規模なデータセットを持ち、主成分（固有ベクトル）の一部のみを計算したい場合、Lanczosアルゴリズムを用いると、
効率的に大規模データセットの特定数の固有ベクトルや固有値を算出することができます。



## まとめ
PCA、SVD、およびLanczosアルゴリズムの関係性は、行列の固有ベクトルと固有値に共通しています。
PCAはSVDを使用して計算でき、
Lanczosアルゴリズムは大規模なPCAのアプリケーションにおいて役立つ一部の固有ベクトルを効率的に計算するときに使える様です。


今回はこの辺がふわっと理解できた位にとどめておきます。

今回はこの辺で。
Cocoonでサイト作り（概要のみ）

# コーポレートサイト作り
今回はCocoonでサイトを作ってみようと思います。
[cocoon](https://wp-cocoon.com/)は結構シェアの高いテーマで、しかも無料です。
詳細については、各自で調べてみて下さい。それなりに情報は転がっています。

1. [インストール](https://wp-cocoon.com/downloads/)
1. [ボックスメニュー](https://wp-cocoon.com/box-menu-widget/)

## サイト編集について
cocoonをインストールし終わったら、基本的にいじるのはカスタマイズ（テーマ->）とcocoon設定のみである。
サイトに必要な画像などはメディアで新規追加しておくように。

## お問い合わせフォームの参考記事
https://web-dev.tech/wordpress/plugin/wp-forms-from-installation-to-setup/

## 固定ページの更新ができなくなった場合
固定ページを編集後、更新ができない問題が発生しました。
編集ページを一旦落としてから、新たなタブから開いても更新ができなかった。

パーマリンクを一時保存したら固定ページの更新が成功した。
Slackで「スレッドを読み込めませんでした」と表示される原因と解決法

Slackで「スレッドを読み込めませんでした」と表示されて利用できないケースがあります。
この記事では、こうしたケースで取れる対処法や原因、トラブルの詳細についてスクショ付で詳しく解説します。
https://app-love.net/slack-cannot-seem-to-load-threads/
Next.jsにおけるPre-rendering: SSRとSSGについて

React 界隈でいま最も勢いのあるフレームワークは、Next.js です。Next.js は React に最適化されたルーティングやミドルウェア機能を標準搭載し、そして SSR 機能も提供してくれるフレームワークです。

Next.jsはReactのエコシステム内で急速に普及しているフレームワークであり、その強力なPre-rendering機能が大きな魅力となっています。この記事では、その2つの主要なPre-rendering手法、SSRとSSGの違いと実装方法について詳しく解説します。

#### 1. Server Side Rendering (SSR)

##### 定義:

SSRは、クライアントからのリクエストがあるたびにサーバー上でページをレンダリングする方法です。

##### 実装方法:

Next.jsでのSSRの実装は非常にシンプルです。ページコンポーネント内で`getServerSideProps`関数を定義するだけです。

１．ユーザーからのリクエストがサーバーに送信される。
２．サーバーはリクエストごとにページをレンダリングします。
３．レンダリングされたページがユーザーに返され、ブラウザで表示されます。

```jsx
export async function getServerSideProps(context) {
  // データフェッチやDBのクエリをここで行う
  const data = await fetchData();

  return {
    props: { data }
  };
}

function MyPage({ data }) {
  return (
    <div>
      {/* レンダリングのロジック */}
    </div>
  );
}

export default MyPage;
```

##### 特徴と利点:

- リアルタイムのデータを表示するのに適しています。
- SEOのメリットがあります。検索エンジンはサーバーから返されるHTMLを直接クロールできます。
- クッキーやユーザーエージェントなどのサーバーサイドの情報にアクセスできます。

##### デメリット:

- トラフィックが多い場合、サーバーに大きな負荷がかかります。
- CDNの利用が難しくなります。

#### 2. Static Site Generation (SSG)

##### 定義:

SSGは、ビルド時にページのHTMLを一度だけ生成し、その後はそのHTMLを再利用する方法です。

##### 実装方法:

Next.jsでのSSGの実装もSSRと同様に簡単です。ページコンポーネント内で`getStaticProps`関数を定義するだけです。
１．ビルドプロセス中にページが一度レンダリングされ、その結果がサーバーに保存されます。
２．ユーザーからのリクエストが来るたびに、保存されたページが提供されます。
３．ユーザーのブラウザでページが表示されます。

```jsx
export async function getStaticProps() {
  // ビルド時にデータフェッチやDBのクエリを行う
  const data = await fetchData();

  return {
    props: { data },
    revalidate: 60 // オプション: 60秒後に再生成
  };
}

function MyPage({ data }) {
  return (
    <div>
      {/* レンダリングのロジック */}
    </div>
  );
}

export default MyPage;
```

##### 特徴と利点:

- 高速なパフォーマンスを提供します。すでに生成されたHTMLが返されるため、サーバーのレンダリングが不要です。
- CDNとの相性が非常に良く、世界中のエッジサーバーでコンテンツをキャッシュできます。
- SEOのメリットもあります。

##### デメリット:

- ビルド時にしかHTMLが生成されないため、リアルタイムの更新が難しいです。ただし、`revalidate`オプションを使用して、定期的に再生成を行うことができます。

### どちらを選ぶべきか?

- **SSR**は、リアルタイムのデータやサーバーサイドの情報が必要な場合に適しています。
- **SSG**は、静的なコンテンツや更新頻度が低いページ、高速な読み込みを求めるページに適しています。

### まとめ

Next.jsは、SSRとSSGの両方のメリットを活かすことができる強力なフレームワークです。プロジェクトの要件や特性に応じて、適切なPre-rendering手法を選択することが大切です。
【TypeScript】 論理演算子 0を許可する時は「||」と「&&」どちらか

## 達成したかったこと

POSTメソッドのAPI開発にて、bodyでリクエストされる項目で、

0がリクエストされたときにそのままDB(PostgreSQL)に登録したい。


ex) ※header省略
```
curl --location 'http://127.0.0.1:3001/profile' 
--data '{
    "name": "urakata",
    "age": 20,
    "salary": 0,
}'
```

## 詰まったこと

リクエスト値のバリデーションチェックのために、

class-validator を使用して型のチェックを行っているが、

0 でリクエストされた値がDB登録時に NULL になってしまっていた。

## 原因
この記述だと、salaryが0でリクエストされたとき、falsyとしてみなされてしまう
```
this.salary = salary || undefined;
```

## 解決策
この記述だと、nullとundefinedのみfalsyとみなすので、期待通りになる。
```
this.salary = salary ?? undefined;
```

## 参考文献
https://zenn.dev/fujii0112/articles/78fe69c4c30731
【Laravel Sail】エイリアスの設定方法 

# はじめに
Laravel Sailを使用して環境構築を行いました。
起動時などのコマンド入力が長く、面倒なのでエイリアスを設定しました。
その手順のメモになります。


:::note warn
Laravel Sailの導入方法は記載していません。
:::

## 動作環境
- macOS Venture 13.5
- zsh

### 1.sailの停止
sailが起動している場合は、設定の前に停止する。
```zsh:zsh 
 ./vendor/bin/sail stop
```

### 2.ホームディレクトリに移動
下記コマンドでホームディレクトリに移動。
```zsh:zsh 
cd 
```
### 3.設定ファイルの確認
ホームディレクトリに移動できたら、下記コマンドで`.zshrc`ファイルがあるか確認する。
```zsh:zsh 
ls -a
```
確認できたら下記コマンドでファイルを開く。
```zsh:zsh 
open ~/.zshrc
```

### 4.ファイルの編集
ファイルを開けたら、以下の文をファイルに記入する。
```zsh:zsh 
alias sail="./vendor/bin/sail"
```
### 5.変更を反映する
下記コマンドをターミナルで実行すれば、ファイルの変更が反映される。
```zsh:zsh
source ~/.zshrc
```

以上で設定が完了できました。

# 設定後のコマンド
Laravel sailの起動
```zsh:zsh 
sail up -d
```
Laravel sailの停止
```zsh:zsh 
sail stop
```
# おわりに
エイリアスを設定することで、長かった起動・停止コマンドを簡略化できました。
設定ファイルの変更方法は、PATHを通す時にも使うので覚えておきたいです。
macで .DS_Storeだけの空ディレクトリを全部削除したい

gitでごっそり違うブランチに切り替えたりすると、切り替え先には存在しなかったファイルはごっそり消えるけど、ディレクトリはごっそり残ってしまって気持ち悪い。

まちがえてフォルダ内を辿って、ああそうだった空だ。。。ってなる。

```
find . -type f -name ".DS_Store" -print | xargs -t -IHOGE rm "HOGE"
```
これと
```
find . -type d -empty -print | xargs -t -IHOGE rm -rf "HOGE"
```
これをターミナルから叩いて、何も表示されなくなるまで繰り返せばOK。

暇あるひと、上の２つを組み合わせてシェルプロ書いてー。出力結果を適当な作業ファイルにリダイレクトして、出力結果ファイルのサイズが0になるまでループさせれば良いだけだと思うので。
IT業界未経験の32歳バカがIT企業に就職するには？

# とりあえず、何をすりゃいいん？
いきなり未経験、資格無しのバカを雇ってくれるIT企業なんてありません。←そりゃそうだ。

じゃあ、どうやったら就職できるん？
って事で、就労支援事業所とか、いろいろ電話したりして調べました。

流れとしては、こんな感じになります。

* とにかく勉強
* 勉強したこと実際にやってみて、身に付ける。
* 上記を繰り返して、何か成果物を作成
* 成果物に関するポートフォリオを作成
* 転職エージェントにてポートフォリオを使い自分をアピールして転職

って流れになります。
就労支援事業所の担当者曰く、

> 資格よりも何ができるか。経験の方が重視されます。

との事です。

つまり、最短でIT企業に就職するには資格よりも先に、とっとと成果物を作る必要があるようですね。

そして、俺のように何かしら仕事をしている人は、就労支援施設の支援が受けられないそうです。
つまり…

**自分で勉強するしかねぇーーー！！！**

まぁ、今ならChatGPT先生に聞けば何でも教えてくれるんで、スクールに通う必要は無いですね。

自分のペースで気長にやります！
[JSTQB AL TA] シラバスを視覚的にまとめてみたシリーズのインデックス

2023年8月のJSTQB　Advanced Level Test Analyst(TA)の試験を受験してきました、Ma5am1nです。
これまでまとめてきた、TAの[シラバス](https://jstqb.jp/dl/jstqb.jpdlJSTQB-SyllabusALTA_V311.J03.pdf)[^1]を視覚的にまとめてみたシリーズのインデックスを作成しました。

[^1]: Advanced Level シラバス日本語版　テストアナリスト　Version 3.1.1.J03 

# インデックス

[1.テストプロセスにおけるテストアナリストのタスク](https://qiita.com/Ma5am1n/items/1b4481bc507a38daa0c7)
　1.1イントロダクション
　1.2ソフトウェア開発ライフサイクルにおけるテスト
　1.3テスト分析
　1.4テスト設計
　　1.4.1ローレベルテストケースとハイレベルテストケース
　　1.4.2テストケースの設計
　1.5テスト実装
　1.6テスト実行

[2.リスクベースドテストにおける テストアナリストのタスク](https://qiita.com/Ma5am1n/items/4fccd5b0f2d417fa4d73)
2.1イントロダクション
2.2リスク識別
2.3リスクアセスメント
2.4リスク軽減
　2.4.1テストの優先度付け
　2.4.2将来のテストサイクルに向けたテストの調整

[3.テスト技法](https://qiita.com/Ma5am1n/items/61e033dccfb5eed8d9df)
3.1イントロダクション
3.2ブラックボックステスト技法
　3.2.1同値分割法
　3.2.2境界値分析
　3.2.3デシジョンテーブルテスト
　3.2.4状態遷移テスト
　3.2.5クラシフィケーションツリー技法
　3.2.6ペアワイズテスト
　3.2.7ユースケーステスト
　3.2.8技法の組み合わせ
3.3経験ベースのテスト技法
　3.3.1エラー推測
　3.3.2チェックリストベースドテスト
　3.3.3探索的テスト
　3.3.4欠陥ベースのテスト技法
3.4最善の技法の適用

[4.ソフトウェア品質特性のテスト](https://qiita.com/Ma5am1n/items/8cc28a87f0012b7ec574)
4.1イントロダクション
4.2ビジネスドメインテストの品質特性
　4.2.1機能正確性テスト、4.2.2機能適切性テスト
　4.2.3機能完全性テスト
　4.2.4相互運用性テスト
　4.2.5使用性テスト
　　4.2.5.1使用性の側面
　　4.2.5.2使用性評価手法
　4.2.6移植性テスト

[5.レビュー](https://qiita.com/Ma5am1n/items/7fcb75b4d0a52e41bd0d)
5.1イントロダクション
5.2レビューでのチェックリストの利用
　5.2.1要件レビュー
　5.2.2ユーザーストーリーレビュー
　5.2.3チェックリストの調整

[6.テストツールおよび自動化](https://qiita.com/Ma5am1n/items/ee9968ed82908a20c9a6)
6.1イントロダクション
6.2キーワード駆動テスト
6.3テストツールの種類
　6.3.1テスト設計ツール、6.3.2テストデータ準備ツール、6.3.3テスト自動実行ツール
macOSでの Java SE 8, 11, 17 のアンインストール方法

### 参照Webサイト
<dl>
  <dt>Java SE 8 のアンインストール方法</dt>
  <dd><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jdk.html#uninstall">https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jdk.html#uninstall</a></dd>
  <dt>Java SE 11 のアンインストール方法（Uninstalling the JDK on macOS 節を参照）</dt>
  <dd><a href="https://docs.oracle.com/en/java/javase/11/install/installation-jdk-macos.html">https://docs.oracle.com/en/java/javase/11/install/installation-jdk-macos.html</a></dd>
  <dt>Java SE 17 のアンインストール方法（Uninstalling the JDK on macOS 節を参照）</dt>
  <dd><a href="https://docs.oracle.com/en/java/javase/17/install/installation-jdk-macos.html">https://docs.oracle.com/en/java/javase/17/install/installation-jdk-macos.html</a></dd>
</dl>

### アンインストール方法
1. 管理者ユーザーでログインします。
1. Finder で、「/アプリケーション/ユーティリティ」フォルダを開いてから、「ターミナル」をダブルクリックします。
1. 「ターミナル」に下記を入力し実行します。（ログインパスワードの入力を求められる場合があります）
    - Java SE 8 の場合
        ```
        cd /Library/Java/JavaVirtualMachines
        sudo rm -rf jdk-1.8.jdk
        ```
    - Java SE 11 の場合
        ```
        cd /Library/Java/JavaVirtualMachines
        sudo rm -rf jdk-11.jdk
        ```
    - Java SE 17 の場合
        ```
        cd /Library/Java/JavaVirtualMachines
        sudo rm -rf jdk-17.jdk
        ```
1. エラー等が表示されなければ、アンインストール完了です。
Djangoで多言語対応を実現する方法

こんにちは！
<a href="https://axlbit.com/" rel="nofollow noopener" target="_blank">AXLBIT株式会社</a>の<a href="https://qiita.com/ax-yang" rel="nofollow noopener" target="_blank">@yang</a>です。

今回は、Django 3.0以降で多言語対応開発する方法についてお話しします。

多言語対応は、ユーザーが異なる言語でコンテンツを表示できるようにする重要な要素です。この記事では、Djangoの多言語対応を実現する方法を説明いたします。

# 言語設定の有効化

デフォルトの言語と利用できる言語のリストを定義するために、まずsettings.pyファイル内で以下例のように言語設定を有効にします。

```python
from django.utils.translation import gettext_lazy as _

LANGUAGE_CODE = 'ja'  # デフォルトの言語設定
LANGUAGES = [
    ('ja', _('Japanese')),
    ('en', _('English')),
    # 他の言語を追加
]
```

多言語の設定を完了した後、次にコード内で多言語対応したい箇所で翻訳のコードを書き込みます。
対応する箇所のファイルタイプによって、コードの書き方は少々違いがあります。

# テンプレートの多言語対応

テンプレート内のテキストを多言語対応する必要がある場合、つまりHTMLファイルで多言語対応する場合、{% trans %} テンプレートタグを使用してテキストを翻訳します。

```html
{% load i18n %}

<h1>{% trans "Multilingual Sample" %}</h1>
<p>{% trans "This is a sample code for multilingual support." %}</p>
```

# Pythonコードの多言語対応

多言語対応は、Pythonコード内でも活用できます、以下の例のようにdjango.utils.translationには翻訳用の関数を用意しております。

```python
# models.py
from django.db import models
from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _

SAMPLE_DATA = [
    {'key': 'sample', 'text': ugettext('Sample')},
]

class Sample(models.Model):
    sample = models.CharField(_('Sample'), max_length=50)
```

ここでugettextとugettext_lazyの二つの関数を利用しました、両者の違いは以下です。

### ugettext_lazy

* テンプレートやモデルのフィールドといった遅延評価が必要なコンテキストで使用されます。
* 文字列を翻訳せず、文字列そのものをラップし、テンプレートがレンダリングされる際やモデルのデータがクエリされる際に翻訳を遅延させます。これにより、適切な言語が選択され、ユーザーに表示されるまで待つことができます。

### ugettext

* 翻訳を即座に評価する関数です。文字列を翻訳し、その結果を返します。
* 主にPythonコード内で使用され、静的なテキストやメッセージを翻訳するのに適しています。

# JavaScriptコードの多言語対応

多言語対応は、JavaScriptコード内でも活用できます。

```javascript
var text = gettext('Sample Text');
```

# 翻訳メッセージの設定

アプリケーション内のテキストを翻訳可能にするために、翻訳メッセージを設定します。以下コマンドを実行します。

```bash
python manage.py makemessages -l ja
python manage.py makemessages -l en
```

これで/local/ja/と/local/en/がそれぞれ作成されます。

しかしこれだけでJSファイルの中の翻訳が追加されません、そのために以下コマンドを実行します。

```bash
django-admin.py makemessages -d djangojs -l ja
django-admin.py makemessages -d djangojs -l en
```

これでpublicの下に/local/ja/と/local/en/がそれぞれ作成されます。

以上コマンドで作成した.poファイルを編集し、翻訳後の文言を入れた後、以下コマンドを実行します。

```bash
python manage.py compilemessages
```

これで.poファイルから.moファイルが作成されて、翻訳メッセージとして利用できます。

# 言語切り替えの実装

ユーザーが言語を切り替えられるように、テンプレートに言語切り替え機能を実装します。

```html
<!-- templates/base.html -->
{% load i18n %}

<div id="language-switcher">
    <a href="?language=ja" class="{% if request.LANGUAGE_CODE == 'ja' %}active{% endif %}">日本語</a>
    <a href="?language=en" class="{% if request.LANGUAGE_CODE == 'en' %}active{% endif %}">English</a>
    <!-- 他の言語を追加 -->
</div>
```

ここでactiveクラスに対して、CSSなどを編集すると、スタイル違いやクリックできないようにすることなどで、現行の言語と表記できます。



# まとめ

Djangoを使用して多言語対応のウェブアプリケーションを構築する方法を詳しく説明しました。多言語対応は、ユーザーエクスペリエンスを向上させるために不可欠な要素です。この記事がお役に立てれば幸いです。
滅びの呪文と呼ばれているrm -rfコマンドについて調べてみた


## そもそもrmコマンドとは？
rm(remove)コマンドはLinuxコマンドの一種で、ファイルを削除するために使用されるコマンドです。
削除したいファイルが存在するディレクトリに移動し、ls -laコマンドで削除したいファイルの存在を確認した後、rm ファイル名と入力することでファイルを削除できます。

## ディレクトリを削除する方法
ディレクトリを削除するには、先ほどのrmコマンドに-rオプションを付けて使用します。具体的にはrm -r ディレクトリ名と入力することでディレクトリを削除できます。
-rオプションは、指定されたディレクトリを再帰的に削除することを意味します。再帰的な削除とは、指定されたディレクトリ内のすべてのファイルやサブディレクトリを削除することを指します。また、削除しようとするファイルやフォルダにパーミッションで制限がかかっている場合、確認メッセージが表示されます。

パーミッションに関する詳細な情報は、以下の記事を参考にしてください。
https://qiita.com/shisama/items/5f4c4fa768642aad9e06

## rm -rfコマンドについて
rm -rfコマンドは、実行するとrm -rに比べて警告メッセージなしに指定したファイルやディレクトリを削除します。もし、`rm -rf /`を実行してしまった場合は、<font color="red">PC内のすべてのファイルやディレクトリが削除されてしまい、取り返しのつかない状態になってしまいます。</font>そのため、rm -rfコマンドを実行する際には非常に注意してください。
Svelteでn回ループ表示させたい時の書き方を考える

# はじめに
Svelteでn回ループ表示させたい場合の書き方について考えてみます。

# バージョン
Svelte 4.2.0


# 一般的な書き方
Svelteでn回ループ表示させたい場合は以下のように書くのが一般的だと思います。
これでも充分動くので良いですが、せっかくSvelteの構文で書いているのに少し冗長な気がします。
いくつか別のアプローチを考えてみましょう。

例:1
```svelte
{#each Array(n) as _, i}
  <p>{i}</p>
{/each}
```
例:2
```svelte
{#each { length: n } as _, i}
  <p>{i}</p>
{/each}
```

# アプローチ1 `range`ヘルパーメソッドを作成する

`range`ヘルパーメソッドを作成します。
別途メソッドを用意する必要はありますが、スッキリと読みやすい印象です。

```js:helper.ts
export function* range(start:number, end:number) {
  for (let i = start; i < end; i++) {
    yield i;
  }
}
```

```svelte:App.svelte
<script>
 import { range } from './helper.ts';
</script>

{#each range(0,5) as i}
  <p>{i}</p>
{/each}
```

# アプローチ2 `<Range>`コンポーネントを作成する

先程作った`range`ヘルパーメソッドをwrapした`<Range>`コンポーネントを作成します。
`start`,`end`のプロパティでわかりやすいですし、`i(index)`も不要であれば呼び出し側で省略できます。
よりシンプルでわかりやすい印象です。
ただ、`{#each}`を隠蔽しているのでループしていることが理解しづらいかもしれません。
(`<Loop>`コンポーネントのほうがわかりやすい？ :thinking: )

REPL: https://svelte.dev/repl/4312129c2d3c4cfdbbf9631234009eb3?version=4.2.0

```svelte:Range.svelte
<script lang="ts">
  export let start: number;
  export let end: number;

  function* range(start: number, end: number) {
    for (let i = start; i < end; i++) {
      yield i;
    }
  }
</script>

{#each range(start, end) as i (i)}
  <slot {i} />
{/each}
```

```svelte:App.svelte
<script lang="ts">
　   import Range from "./Range.svelte"
</script>

<Range start={0} end={5} let:i>
　   <p>{i}</p>
</Range>
```

# さいごに
Svelteでn回ループ表示させたい時のいくつかのアプローチを考えてみました。
是非参考にしてみてください。

実はSvelteで`{#range ...}`構文を追加するissueが立っています。
`{#range ...}`が追加されればこれらのアプローチは不要になるので追加されてほしいですね。
2019年に作成以来、動きがないのでいつ追加されるかは不明ですが、Svelte5に期待しましょう。


https://github.com/sveltejs/svelte/issues/2968
インドで SIM を買うのが怖くて airalo を試した

airalo という旅行先で利用できる eSIM を売ってくれるサービスを使ってみました。

というのも、旅行日程が17日間に対して ahamo は15日間経過すると 128 kbps になってしまうことから SIM の購入を検討したのですが、インドでのツーリスト SIM の購入は、アクティベーションという手続きが必要で購入後しばらく利用できない、買ったのに使えなかった人もいるらしいなどと、不安になる情報が多くあったためです。

アフィリエイトのない記事が見当たらなかったこともあり、メモのような形ですが記事にすることにしました。


## 注意点

1. SIM フリーである必要がある
1. eSIM が使える機種である必要がある
1. eSIM のローミングを有効にする必要がある（主回線のローミングとは設定が別）
1. Airtel 回線だが、Airtel で契約するよりは遅いらしい (格安 SIM の docomo 回線のようなもの？)
1. 電話番号はない（インドではしばしば記入を求められる）


## 簡単な手順

格安 SIM などで SIM を交換したことのある人には難しくありません。

1. airalo の初回割引コードはいろんな人が配布してる。使うと3ドル安くなる。
1. 少なめの容量で契約する。万一足りなくなっても ahamo などでインターネットが繋がるならいつでも同額でチャージできるため。
1. QR コードから eSIM を追加する。私の環境ではこの段階でソフトバンクの電波を掴みました。
1. **追加した eSIM のローミングを有効にする**
1. アプリをダウンロードしてログインしておく。設定方法などを読める。データの残量確認やチャージもできる。
1. 機内でモバイルデータ通信を主回線から eSIM の回線に切り替える。


## 感想

デリーの空港ですぐに繋がるのか、インターネット共有（テザリング）が使えるのかが心配でしたが、いずれも問題なく快適で、現代的で良いサービスだと思いました。速度も ahamo と同程度のように感じました（計測していません）。

ただ、主回線と副回線の切り替えはうまくいかずに端末の再起動で解決したことが何度かありました。

この記事は技術的な内容ではありませんが、オフショア先のインドを訪問するというのは定期的に聞く話であり、エンジニア ライフに関係することとして投稿しました。
[小ネタ] AWS Glue/PySparkで出力するCSVのレコード区切りをCRLFにする [懸念あり]

# 結論

- DynamicFrameやSparkのDataframeではCRLFにできないし、デフォルトはLF
- toPandas()してlineterminatorで指定する

## なんでCRLFにしたいのか

世の中のCSVは相当カオス。少しでも”標準”的に作りたい。
実現が難しくないならちゃんとRFCに準拠してあげたい。

さて、レコード区切りは何が標準なのだろうか？

[RFC 4180: Common Format and MIME Type for Comma-Separated Values (CSV) Files](https://www.rfc-editor.org/rfc/rfc4180)

> Each record is located on a separate line, delimited by a line break (CRLF).

このように書かれています。

[RFC 7111 - URI Fragment Identifiers for the text/csv Media Type](https://datatracker.ietf.org/doc/html/rfc7111)

>    Encoding considerations:  CSV MIME entities consist of binary data [RFC6838].  As per Section 4.1.1. of RFC 2046 [RFC2046], this media type uses CRLF to denote line breaks.  However, implementers should be aware that some implementations may use other values.

こちらもCRLFだとしつつも、実装次第？？？うーん・・・・

## Glueってどうなのか

[Using the CSV format in AWS Glue - AWS Glue](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-csv-home.html)

> AWS Glue supports using the comma-separated value (CSV) format. This format is a minimal, row-based data format. CSVs often don't strictly conform to a standard, but you can refer to RFC 4180 and RFC 7111 for more information.

・・・サポートとは？文が切れているので、RFC 4180/7111の通りだ、とは言っていないようにも読める。

結局できるのか、できないのか、どっちなんだい。

## まずDynamicFrame

[上記のドキュメント](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-csv-home.html)の下の方を見ていきますが・・・

レコード区切りに関するオプションがない。。。

## SparkのDataframeなら・・・

[pyspark.sql.DataFrameWriter.csv — PySpark 3.1.2 documentation](https://spark.apache.org/docs/3.1.2/api/python/reference/api/pyspark.sql.DataFrameWriter.csv.html)

> **lineSep : *str, optional***
defines the line separator that should be used for writing. If None is set, it uses the default value, \\n. Maximum length is 1 character.

デフォルトはLFになっています。（RFC 4180/7111を無視しちゃいませんか？）

で、ここをCRLFにすれば良さそうなのだが・・・・

[[SPARK-34529] spark.read.csv is throwing exception ,"lineSep' can contain only 1 character" when parsing windows line feed (CR LF) - ASF JIRA](https://issues.apache.org/jira/browse/SPARK-34529?focusedCommentId=17292637&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-17292637)

なんと、1文字しか許容していない。
CRLF(\r\n)を指定すると、

`pyspark.sql.utils.IllegalArgumentException: requirement failed: 'lineSep' can contain only 1 character.`

見事にExceptionとなってしまう。

## ではPandasだ

仕方ない・・・・

```
spark_df = source_dynamicframe.toDF()
pandas_df = csv_df.toPandas()
pandas_df.to_csv(output_path, lineterminator = "\r\n")
```

こうなっちゃう。

## あれれ？

Pandasになっちゃうとしたら、そもそもなんでSpark(PySpark)使ってるんだっけ？との疑問が当然にでてまいります。
並列分散処理できなくなるため、大量データをCSV出力する場合には留意が必要と考えられます。（まだ試せてはいない）

CRLFを求めるようなシステムは、1ファイルにまとめてほしかったりもするケースが多いような感覚がありますので、実質は許容できる制約なのかもしれません。

## モヤッとすること

RFCはなんでCRLFと書いているのだろう・・・
Nuxt3 + vue fontawesome で Hydration node mismatch warnがでた

ので、調べた。

## 概要
Nuxt3 に Fontawesome を利用したいので、
https://fontawesome.com/v6/docs/web/use-with/vue/use-with#nuxt
を参考に設定してみた。

・・・が、開発サーバー（localhost）起動時、ブラウザで以下のエラーがでた。

```
[Vue warn]: Hydration node mismatch
```

ターミナル側は、こんなメッセージが表示されていた。
```bash
✔ Nitro built in 2295 ms                                                               nitro 11:56:33
Could not find one or more icon(s) { prefix: 'fab', iconName: 'instagram' } {}
```

## 環境
- nuxt: v3.7.0
- @fortawesome/fontawesome-svg-core: v6.4.2
- @fortawesome/free-brands-svg-icons: v6.4.2
- @fortawesome/vue-fontawesome: v3.0.3

## ソースコード

`plugins/vue-fontawesome/vue-fontawesome.ts`
```ts
import { library, config } from '@fortawesome/fontawesome-svg-core';
import {
  faInstagram as fabInstagram,
} from '@fortawesome/free-brands-svg-icons';

config.autoAddCss = false;

library.add(fabInstagram);

export default defineNuxtPlugin(() => {});
```

`nuxt.config.ts`
```ts
export default defineNuxtConfig({
  // 指定しなくてもよいらしいが、auto-importが好きでないのでimport元を指定してる
  plugins: [
    {
      src: '@/plugins/vue-fontawesome/vue-fontawesome.ts',
    },
  ],
});
```

## どうやって修正した？
`build.transpile` に fortawesome関連を追加した。
```diff
export default defineNuxtConfig({
+  build: {
+    transpile: [
+      '@fortawesome/vue-fontawesome',
+      '@fortawesome/fontawesome-svg-core',
+      '@fortawesome/free-brands-svg-icons',
+    ],
+  },

  plugins: [
    {
      src: '@/plugins/vue-fontawesome/vue-fontawesome.ts',
    },
  ],
});
```

## 参考URL
- https://github.com/FortAwesome/vue-fontawesome/issues/394
- https://github.com/nuxt/nuxt/discussions/16014#discussioncomment-2477885

参考URLの内容をまとめただけの記事ですみません。
誰かの役に立つよいなと思いつつ。
ローカルで作成した「ASP.NET Core MVC」アプリをＡＷＳ環境にて動作確認を行う。

【目的】ローカル端末のvisualstudioで作成したアプリをAWS環境へデプロイを行い動作確認をする。

【背景】MSの手順に則って実施したが、苦戦した点、対応できなかった点を備忘録として残す。

【実施した内容】
1. ローカル端末のvisualstudioで「ASP.NET Core MVC」アプリを作成する
2. 作成したアプリの発行を行う
3. 発行したアプリをAWS環境へデプロイする

【1. ローカル端末のvisualstudioで「ASP.NET Core MVC」アプリを作成する】
①以下のMSサイトの手順（パート4まで）に基づいて、アプリの作成を行う。
URL：https://learn.microsoft.com/ja-jp/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-6.0&tabs=visual-studio

②パート1：新しいプロジェクトを作成して、アプリを実行する。

③パート2：アプリにコントローラーを追加する。

④パート3：アプリにビューを追加をする。

⑤パート4：アプリにモデルを追加する。

【2. 作成したアプリの発行を行う】
visualstudioにて、以下の手順で行う。
①右ペインのプロジェクトを右クリックして、「発行」をクリックする。

②発行先のフォルダを任意の箇所を設定する

③発行ボタンを押下する

【3. 発行したアプリをAWS環境へデプロイする】
①発行したフォルダを「C:\inetpub\wwwroot」へ配置する

②IISを起動後、「アプリケーションプール」を選択し、右クリックから「アプリケーションプールの追加」をクリックする

③任意の名前を入力し、「OK」ボタンを押下する。

④左ペインの「Default Web Site」を右クリックし、「アプリケーションの追加」をクリックする

⑤「エイリアス」に任意の名前を入力する。

⑥選択ボタンを押下し、「アプリケーションプール」を3. で設定した名前を選択する

【4.動作確認①】
①左ペインから対象のアプリケーションを選択し、右ペインの「アプリケーションの参照」を押下する

②実行したところ以下のようなエラーが出力され、想定した結果を得ることができなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551691/fa756b50-7282-c437-2a0b-ee93daf32b91.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551691/78821c9b-7535-5a28-ade4-5164d3c06687.png)

③以下の記事の対応をしたところ、出力されるエラーが減った。
URL：https://learn.microsoft.com/ja-jp/archive/blogs/sqlexpress/using-localdb-with-full-iis-part-1-user-profile
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551691/b51399d4-3abf-6bc7-bcfc-64fabd9abd64.png)

④ほかにもネットで調査したところ、下記記事のようにLocalDBを使用してIISでは上手く動作しない旨の記載があった。
URL：https://atmarkit.itmedia.co.jp/ait/articles/1811/13/news029_2.html

⑤解決に至らなかったため、以降に記載する方法で動作確認を行った。

【5.動作確認②】
【1. ローカル端末のvisualstudioで「ASP.NET Core MVC」アプリを作成する】の手順にて、MSサイトのパート4まで手順にてアプリを作成したが、今回の目的は、「ローカルで作成したアプリをAWS環境へデプロイして動作確認を行う」であったため、パート4に記載のある、LocalDBを使用するアプリは作成せず、【2. 作成したアプリの発行を行う】、【3. 発行したアプリをAWS環境へデプロイする】を行った。

上記の対応をしたところ、問題なく期待値通りの動作確認をすることができた。


【6.さいごに】
エラーが発生した箇所の根本的な解決には至らなかったが、ローカル端末で作成したアプリをＡＷＳ環境へデプロイを行い、動作を確認することができた。
w3m install RockyLinux8 (nothing provides perl(NKF))

# w3m install error

## w3mインストールでエラーで怒られる RockyLinux8
```console
dnf install --nobest w3m
Error:
 Problem: conflicting requests
  - nothing provides perl(NKF) needed by w3m-0.5.3-60.git20230121.el8.x86_64
(try to add '--skip-broken' to skip uninstallable packages)
```

## powertoolsレポジトリを有効にしてinstall

```sh
dnf --enablerepo powertools install w3m
```
perl-NKFがpowertoolsレポジトリからinstallされる。

### powertools?

最初から入ってるので要件によって```set-enabled```とかすれば良いのかな。

```console
$ cat /etc/yum.repos.d/Rocky-PowerTools.repo
# Rocky-PowerTools.repo
#
# The mirrorlist system uses the connecting IP address of the client and the
# update status of each mirror to pick current mirrors that are geographically
# close to the client.  You should use this for Rocky updates unless you are
# manually picking other mirrors.
#
# If the mirrorlist does not work for you, you can try the commented out
# baseurl line instead.

[powertools]
name=Rocky Linux $releasever - PowerTools
mirrorlist=https://mirrors.rockylinux.org/mirrorlist?arch=$basearch&repo=PowerTools-$releasever
#baseurl=http://dl.rockylinux.org/$contentdir/$releasever/PowerTools/$basearch/os/
gpgcheck=1
enabled=0
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
```
【JavaScript】数値の桁数を得る

# 概要
桁数を得る関数の公開・共有

## 動機
jsにおける数値の桁数取得についてググったが
専用の標準機能はなかったので作成


## 処理の流れ
入力値は小数値を切り捨てた絶対値に変換して扱う。

変換後の値が0である場合は、
zeroDigitパラメータで指定された引数を返す。

0に対する桁数の解釈は諸説(0,1,-Infinity)ある。
故にTwitter上で行われていたアンケートにおいて、
最多票数を得た1をzeroDigitのデフォルト値とする。

また、変換後の値が0以外である場合は、
⌊log10(n)+1⌋ により桁数判定を行う。

## コード
```
function digit(number, zeroDigit = 1){
  const number_ = Math.floor( Math.abs(number) )
  const isZero = number_ == 0
  const isZeroFunc = () => zeroDigit
  const notZeroFunc = () => Math.floor( Math.log10(number_) ) + 1
  const currentFunc = isZero ? isZeroFunc : notZeroFunc
  const result = currentFunc()
  return result
}
```

## 実行結果
```
digit(0)    // -> 1
digit(0.01) // -> 1
digit(9)    // -> 1
digit(10)   // -> 2
digit(-50)  // -> 2
digit(0,0)  // -> 0
```
文章中の単語の出現数のカウント

## はじめに
社内で共有する機会があったのでドキュメントがあったほうが良かろうと備忘録も兼ねて簡単に作成してます。
## 環境
- wsl2
- python3.10.12

## パッケージのインストール
```bash
pip install pandas re csv MeCab 
sudo aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file
```

## MeCab-ipadic-NEologdの辞書の追加
```bash
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
```

## パッケージのインポート
```py
import MeCab
import re
import csv
import pandas as pd
```

## csvファイルの読み込み
```py
with open('xxx.csv', 'r', encoding='utf8')as f:
    df = pd.read_csv(f)
```
## 辞書のパスの確認
MeCabで辞書を使うためにはTaggerの中で辞書のパスを指定して上げる必要があります。そのためのパスをechoコマンドで確認しましょう。
```bash
echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
# /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
```

## MeCabで分かち書き
以上を行ったら読み込んだcsvファイルを分かち書きしていきましょう。
今回は分かち書きをした後、名詞だけ取得しています。
```py
# 人によっては以下のパスは異なるので確認してね
mecab = MeCab.Tagger('-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd')
mecab.parse('')  # バグ対処
results = []
lines = df['text']
use_parts = ['名詞']
for line in lines:
    r = []
    # 学習に使わない表現の削除処理
    s = line
    s = s.replace("|", "")
    s = re.sub(r'《.+?》', "", s)
    s = re.sub(r'［.+?］', '', s)
    # Mecab
    node = mecab.parseToNode(s)
    while node:
        # 単語を取得
        if node.feature.split(",")[6] == '*':
            word = node.surface
        else:
            word = node.feature.split(",")[6]

        # 品詞を取得
        part = node.feature.split(",")[0]

        if part in use_parts:
            r.append(word)
        node = node.next
    rl = (" ".join(r)).strip()
    results.append(rl)

print(results)
```
> コード引用元https://qiita.com/sudo5in5k/items/f89d9dc1bec1ed221ede

### MeCabでエラーが出たとき
私の環境では最初動かしたとき、macabrcが見つからねえよハゲとエラーが出ました。下のサイトを参考にした結果直りました。具体的にどうやったかは忘れました。
>https://ikagadeshitaka.hatenablog.jp/entry/2020/09/29/235335
https://github.com/SamuraiT/mecab-python3#common-issues

### ちなみに
MeCab自体の出力はどうなっているのかを知っておくと今後何処かで活かせると思うので念のため記しておきます。
```py
s = '今日はいい天気ですね。'
node = mecab.parseToNode(s)
while node:
    print(node.feature.split(","))
    node = node.next

# ['BOS/EOS', '*', '*', '*', '*', '*', '*', '*', '*']
# ['名詞', '副詞可能', '*', '*', '*', '*', '今日', 'キョウ', 'キョー']
# ['助詞', '係助詞', '*', '*', '*', '*', 'は', 'ハ', 'ワ']
# ['形容詞', '自立', '*', '*', '形容詞・イイ', '基本形', 'いい', 'イイ', 'イイ']
# ['名詞', '一般', '*', '*', '*', '*', '天気', 'テンキ', 'テンキ']
# ['助動詞', '*', '*', '*', '特殊・デス', '基本形', 'です', 'デス', 'デス']
# ['助詞', '終助詞', '*', '*', '*', '*', 'ね', 'ネ', 'ネ']
# ['記号', '句点', '*', '*', '*', '*', '。', '。', '。']
# ['BOS/EOS', '*', '*', '*', '*', '*', '*', '*', '*']
```

## 最後に
あとは単語をキーに出現回数をカウントする辞書を作成しておしまいです。
今回、アルファベットの表記ゆれを防ぐため、全て小文字に直してます。
```py
count_dic = {}
for r in results:
    for w in r.split():
        w = w.lower()
        if w not in count_dic.keys():
            count_dic[w] = 0
        count_dic[w] += 1
sorted_count = sorted(count_dic.items(), key= lambda x:x[1], reverse=True)

with open('test.csv', 'w', newline='')as f:
    writer = csv.writer(f)
    writer.writerows(sorted_count)
```

お疲れさまでした。あとは適当にアレンジして活用してください。おしまい！
【VB.NET】ツールボックスが使えなくなった場合の対処方法

## 経緯
※Visual Studio2019を使用。
原因不明だが、ツールボックスでほとんどの項目がグレーアウトしてしまい、
コンポーネントを追加できなくなった。

## 対処方法
①ツールボックスの**リスト上**で右クリックする。
②`ツールボックスのリセット`を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/5efc6e31-4077-35fa-2dc9-23c9eb7f3881.png)


## 結果
ツールボックスのすべての項目が選択可能になった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/3003577f-5359-c78f-61f0-69904610982e.png)


## 参考サイト
Visual Studioのツールボックスのアイコン表示がおかしくなった場合
https://imagingsolution.net/program/visualstudio/visual-studio-icon/

yahoo知恵袋
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12165357277
Macでgoenvやrbenvを統合して使えるanyenvを試してみる

新しい会社の開発環境構築ドキュメントを見ると、
anyenvという、goenvやrbenvなどが統合されたバージョン管理ツールがあったので試してみる。

既存に入れていたgoenvをアンイストールする。

```zsh
% goenv uninstall 1.20.3
```

```zsh
% brew uninstall goenv
Uninstalling /opt/homebrew/Cellar/goenv/2.1.4... (327 files, 534.7KB)
```

```zsh
% vi ~/.zshrc
```

下記を削除

```.zshrc
echo source '/opt/homebrew/share/google-cloud-sdk/completion.zsh.inc'
echo source '/opt/homebrew/share/google-cloud-sdk/path.zsh.inc'
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
```

ディレクトリも削除

```zsh
% rm -rf /Users/mitsuaki.ihara/.goenv
```

### anyenvのインストール

```zsh
$ brew install anyenv
```

```zsh
% anyenv init
# Load anyenv automatically by adding
# the following to ~/.zshrc:

eval "$(anyenv init -)"
```

.zshrcにも追加しておく。

```zsh
% vi ~/.zshrc
```

```.zshrc
eval "$(anyenv init -)"
```

シェルに再アクセスするとマニフェストがないと言うエラーが出る。

```zsh
% source ~/.zshrc
ANYENV_DEFINITION_ROOT(/Users/mitsuaki.ihara/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
> anyenv install --init
```

インストールを実行

```zsh
% anyenv install --init
Manifest directory doesn't exist: /Users/mitsuaki.ihara/.config/anyenv/anyenv-install
Do you want to checkout https://github.com/anyenv/anyenv-install.git? [y/N]: y
Cloning https://github.com/anyenv/anyenv-install.git master to /Users/mitsuaki.ihara/.config/anyenv/anyenv-install...
Cloning into '/Users/mitsuaki.ihara/.config/anyenv/anyenv-install'...
remote: Enumerating objects: 71, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 71 (delta 4), reused 4 (delta 1), pack-reused 57
Receiving objects: 100% (71/71), 13.15 KiB | 6.58 MiB/s, done.
Resolving deltas: 100% (11/11), done.

Completed!
```

バージョンの確認。

```zsh
% anyenv --version
anyenv 1.1.5
```

パスを通す(これを実行しないとgoenvなどのコマンドが動かない)

```zsh
% echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc
```

## goenvをanyenv経由で取得してくる。

goenvをanyenv経由でインストールする。

```zsh
% anyenv install --list | grep goenv
  goenv
```

```zsh
% anyenv install goenv
/var/folders/vv/vmvy9fnx60j1902dcdfdrx3r0000gn/T/goenv.20230905110555.18046 ~
Cloning https://github.com/syndbg/goenv.git master to goenv...
Cloning into 'goenv'...
remote: Enumerating objects: 15663, done.
remote: Counting objects: 100% (804/804), done.
remote: Compressing objects: 100% (223/223), done.
remote: Total 15663 (delta 598), reused 678 (delta 564), pack-reused 14859
Receiving objects: 100% (15663/15663), 2.93 MiB | 4.40 MiB/s, done.
Resolving deltas: 100% (10323/10323), done.
~

Install goenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.
```

Goをanyenv経由のgoenv経由で再インストール。

```zsh
% cat .go-version
1.20.3
% goenv install 1.20.3
Downloading go1.20.3.darwin-arm64.tar.gz...
-> go1.20.3.darwin-arm64.tar.gz
% go version
go version go1.20.3 darwin/arm64
```

### コメント

言語ごとに◯◯envを入れていたが、統合して管理できるのは便利そう。
しばらく使ってみようと思う。

### 追記

下記指定でダウンロードしたGoのバージョンまでパスを通さないと、
リポジトリ内のMakefileからgo installしたツールが参照できなかった。
バージョンを切り替えるごとにパスを変えるのは疑問に思うので、他に良い設定方法があるように思えるが、
調べても分からず…。

```zsh
% echo 'export PATH="$HOME/go/1.20.3/bin:$PATH"' >> ~/.zshrc
```