OmniAICreator/Qiita-1.07M huggingface dataset:
あるプロセスの環境変数を知る

最近ちょっとした必要に迫られ、あるプロセスの環境変数を取得することになりました

# 結論
`/proc/PID/environ` にそのプロセスの持っている環境変数がセットされています

## 注意事項
各環境変数のKEY=VALUEをNULL文字で結合したものとなっています
つまりそのままだとあまり取り回しが良くありません

# /proc/PID/environの内容を改行区切りで出力する
使い勝手の良い改行区切りのリストを出力するためのスクリプトを用意します

```python:process-env
#!/usr/bin/python3

import os
import sys
import shlex
import re

try:
  with open(f"/proc/{sys.argv[1]}/environ") as f:
    content = f.read();
    envList = content.split("\0")
    pattern = "([^=]+)=(.*)"
    repatter = re.compile(pattern);

    for envLine in envList:
      result = repatter.match(envLine)

      if not result:
        continue

      key = result.group(1)
      value = shlex.quote(result.group(2))
      print(f"{key}={value}")

except FileNotFoundError:
  os._exit(status=255)
```

エラー処理とか適当ですが
これで `process-env 1` とかやると指定したプロセスIDの(起動時に)持っている環境変数を取得できるようになりました

# 雑感
ググったらシェルスクリプトで `strings /proc/PID/environ` で取れるような記事もありましたが、この場合だと値に `$` が含まれる場合に、それをそのままexportするような形にした際にシェルの変数として解釈されてしまいます
`$` という文字として解釈したいのでエスケープするためにpythonでshlex.quoteを使ってエスケープするスクリプトを用意しました
phpでescapeshellarg()を使っても良いでしょう

これで無事にあるプロセスが持つ環境変数を取得して利用することが出来るようになりました

---

それでは良いLinuxライフを
【Go】簡単なGetAPIの作成

# 実装
```go:main.go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// データの構造体 (仮のデータ)
type Data struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func main() {
	// APIエンドポイントのハンドラを登録
	http.HandleFunc("/api/data", getData)

	// サーバーを起動 (ポート: 8080)
	fmt.Println("サーバーを起動します...")
	go func() {
		err := http.ListenAndServe(":8080", nil)
		if err != nil {
			fmt.Println("サーバーの起動に失敗しました:", err)
		}
	}()
	fmt.Println("サーバーは起動しています。")

	// サーバーが起動している間、メインの処理をブロックする
	select {}
}

// テスト用のデータを返すAPIハンドラ
func getData(w http.ResponseWriter, r *http.Request) {
	// テストデータを作成
	data := Data{
		ID:   1,
		Name: "サンプルデータ",
	}

	// データをJSON形式にエンコードしてレスポンスとして返す
	w.Header().Set("Content-Type", "application/json")
	err := json.NewEncoder(w).Encode(data)
	if err != nil {
		http.Error(w, "データのエンコードに失敗しました", http.StatusInternalServerError)
		return
	}
}
```

- 以下のコマンドでサーバーを起動する。
```terminal:terminal
go run main.go
```

- VScodeの拡張機能のThunder clientかPostmanでAPIの動作確認をする。（以下、Thunder clientの画面を掲載）

![スクリーンショット 2023-07-28 19.48.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1850625/3cbd84d2-126c-dffe-570e-6fe5a1b03f85.png)

Thunder clientをインストールすると、左に雷模様のアイコンが追加されるのでクリックする。
New Requestを押し、Getで、http://localhost:8080/api/data
に書き換える。
Sendを押すと、idとnameが返ってくる。
![スクリーンショット 2023-07-28 19.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1850625/732624e4-6e36-cd8c-816d-3076e0aa805c.png)
PHPの将来性

# 目次
1. [PHPとは](#PHPとは)
1. [PHPフレームワークのフリーランス求人・案件数](#PHPフレームワークのフリーランス求人・案件数)
1. [PHPエンジニアの平均年収・年収相場](#PHPエンジニアの平均年収・年収相場)

# PHPとは
1. [概要](#概要)
1. [フレームワーク](#フレームワーク)

### 概要
Webページに動きをつけるために開発された、Web開発に特化したプログラミング言語
「**動的型付け言語**」に分類される
**動的型付け言語**：同じURLでも閲覧者や時間帯などによって、表示される内容が変わるもの

### フレームワーク
**▼Laravel**
2011年に登場したフレームワークであり、PHPフレームワークの中で最高評価を受けている

##### メリット
プログラムの拡張性や自由度が高い

##### デメリット
自由度が高すぎてコードが煩雑化しやすい

<img src="https://mat0401.info/wp-content/uploads/2020/06/laravel_logo.png" />

**▼CakePHP**
2005年に登場したオープンソース型のフレームワーク

##### メリット
学習しやすい
コードに一貫性があり、可読性が高い
公式ページから参加できるコミュニティがあり、情報共有や不具合の報告などが活発に行われる

#### デメリット
他フレームワークと比べて処理速度が遅いため、大規模プロジェクトになるとこのデメリットが出やすくなる
規約が厳しく、カスタマイズ性が低い

<img src="https://cakephp.org/img/trademarks/logo-2.jpg" />


**▼Symfony**
2005年に登場したオープンソース型のフレームワーク
大規模なエンタープライズ向け

#### メリット
コンポーネントベースで高い拡張性を持っている

#### デメリット
学習曲線が急で初心者には難しい。また設定が複雑であるため、慣れるまで時間がかかる

<img src="https://hombre-nuevo.com/wp-content/uploads/2015/07/symfony_black_01.png" />

# PHPフレームワークのフリーランス求人・案件数

**2022年02月**
<img src="https://cf.freelance-start.com/article/pictures/3432/PHP_1-min.png" />

#### Laravelが圧倒的にトップ
PHPフレームワークのトレンドが毎年ほぼ変わらないのを見ると、Laravelからスタートするのが無難

# PHPエンジニアの平均年収・年収相場
求人検索エンジン「スタンバイ」の「[プログラミング言語別 平均年収](https://www.bizreach.co.jp/pressroom/pressrelease/2017/0810.html)」(2017年）によると平均年収は522万円で順位は10位
<img src="https://www.bizreach.co.jp/img/pressroom/pressrelease/2017/0810/capture_01.png" />

# プログラミング言語別求人ランキングTOP5
**2022年1月現在**
Javaに次いで2位
<a href="https://ibb.co/4mcBnJZ"><img src="https://i.ibb.co/j6d7PHv/2023-07-28-195404.png" alt="2023-07-28-195404" border="0" width="120%"></a>
Xcode14.3のwarning : Heterogeneous collection literal could only be inferred to ... について

Xcode14.3からコンパイルでこのようなwarningが出るようになりました。

`
Heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
`

調べてみたところSwift5.8のバグのようで、Swift5.9(Xcode15-beta)で試したところこのwarningは出なくなりました。（Xcode14.3.1では変わらず）
https://forums.swift.org/t/swift-5-8-new-warnings-for-any-collections/63484/2

なので、このwarningは無視してXcode15がリリースされるまで待つでよさそうです。
MathML?「ページのソースの表示」から,タグを削除したい。テスト(1)sin,cos

**いい方法ないですか？**
[アドバイス頂けると幸いです](
https://www.google.com/search?q=%E3%82%A2%E3%83%89%E3%83%90%E3%82%A4%E3%82%B9%E9%A0%82%E3%81%91%E3%82%8B%E3%81%A8%E5%B9%B8%E3%81%84%E3%81%A7%E3%81%99+%E8%8B%B1%E8%AA%9E&rlz=1C1GCEB_enJP1054JP1054&oq=%E3%82%A2%E3%83%89%E3%83%90%E3%82%A4%E3%82%B9%E3%81%84%E3%81%9F&aqs=chrome.4.69i57j0i512l2j0i4i512l3j0i512l4.21407j0j7&sourceid=chrome&ie=UTF-8)


# ChatGPTでテスト(できませんでした。)

以下のMathMLをテキスト表示してほしい
以下のテキストからタグを削除してほしい


# オリジナル

https://qiita.com/mrrclb48z/items/59fd2a0d682efa25b17e


# テスト (awk版)Ver0.1
(1)(2)目的。ゴールです。
```
(cos⁡θ^2+sinθ^2)^3-(cosθ^6+sin⁡θ^6)
(2(cosθ^6+sinθ^6)+1)/3(cosθ^4+sinθ^4)
```

awkの結果
```
(1)　(cos2&af;θ+sin2&af;θ)3-(cos6&af;θ+sin6&af;θ)
(2)　2(cos6&af;θ+sin6&af;θ)+13(cos4&af;θ+sin4&af;θ)
```
awkの結果より
？？？？？？
```
2&af;θ　→　θ^2
他
```

以下より 経営経済学部【１】

https://mathexamtest.web.fc2.com/2017/201711051/2017110510100.html#top-0103

Awk用のInput 「ページのソースの表示」
(1)
```
<p class="s2level">(1)　<math>
<mrow><msup><mrow><mo stretchy="false">(</mo>
<msup><mi>cos</mi><mn>2</mn></msup><mo>&af;</mo>
<mi>&theta;</mi><mo>+</mo><msup><mi>sin</mi>
<mn>2</mn></msup><mo>&af;</mo><mi>&theta;</mi>
<mo stretchy="false">)</mo></mrow><mn>3</mn>
</msup><mo>-</mo><mo stretchy="false">(</mo>
<msup><mi>cos</mi><mn>6</mn></msup><mo>&af;</mo>
<mi>&theta;</mi><mo>+</mo><msup><mi>sin</mi>
<mn>6</mn></msup><mo>&af;</mo><mi>&theta;</mi>
<mo stretchy="false">)</mo></mrow></math></p>
```
(2)
```
<p class="s2level">(2)　<math>
<mstyle displaystyle="true"><mfrac><mrow><mn>2</mn>
<mo>&it;</mo><mo stretchy="false">(</mo><msup>
<mi>cos</mi><mn>6</mn></msup><mo>&af;</mo>
<mi>&theta;</mi><mo>+</mo><msup><mi>sin</mi>
<mn>6</mn></msup><mo>&af;</mo><mi>&theta;</mi>
<mo stretchy="false">)</mo><mo>+</mo><mn>1</mn>
</mrow><mrow><mn>3</mn><mo>&it;</mo>
<mo stretchy="false">(</mo><msup><mi>cos</mi><mn>4</mn>
</msup><mo>&af;</mo><mi>&theta;</mi><mo>+</mo>
<msup><mi>sin</mi><mn>4</mn></msup><mo>&af;</mo>
<mi>&theta;</mi><mo stretchy="false">)</mo></mrow>
</mfrac></mstyle></math>
</p>
```


# 問題文の解答

https://qiita.com/mrrclb48z/items/e14ca9aac758559fb998

# 参考
だそうです。

https://qiita.com/BlueRayi/items/14592301160b29f08bc0
【Laravel／Dusk】waitForを使って無駄なテスト実行時間を短縮する

# はじめに
**①ボタンをクリック**
**②GETリクエスト**
**③レスポンスが返ってきてメッセージ表示**

`Dusk`を使ってテストを書いていると、上記のような流れをテストすることはよくあると思います。
このような一連の流れを確認するにはどのように実装するのが良いでしょうか？

例えば①で`<button dusk="search-button">検索</button>`をクリックして③で`検索結果が0件です。`というメッセージを確認するテストだとして、下記のように実装してみます。

```php
// パターン1
$browser->click('@search-button');
$browser->assertSee('検索結果は0件です。');
```
`click()`で検索ボタンクリックを行い、`assertSee()`でメッセージを確認するシンプルな内容で、テストも問題なく動くかと思います。

しかし、実行環境などによって②のGETリクエストの結果がすぐに返って来なかった場合(スペックが良くない、遅いPCの環境で実行をした場合など)、`assertSee()`での確認に失敗する可能性があります。
これでは環境によって結果が異なってしまうので良くありません。

では以下はどうでしょうか？
```php
// パターン2
$browser->click('@search-button');
$browser->pause(3000);
$browser->assertSee('検索結果は0件です。');
```
パターン1の`click()`と`assertSee()`の間に`pause()`で3秒待機するようにしてみました。
こちらも問題なくテストが実行されると思います。

しかし`pause()`は指定した時間分待機するため、3秒以内で実行できても必ず3秒の実行時間が必要となってしまいます。
1件ならまだしも何度も`pause()`で待機していれば、テスト全体の実行時間は長くなってしまいます。

こんな時にパターン1,2の問題を解決できるのが`clickAndWaitForReload()`です。
```php
$browser->clickAndWaitForReload('@search-button');
$browser->assertSee('検索結果は0件です。');
```
`clickAndWaitForReload()`はボタンをクリックした後**リロードするまで待ってくれます**。
パターン1のように環境によって左右されることもなく、パターン2のように無駄な待機の時間はありません。

リロードした後に何か確認するようなテストは`clickAndWaitForReload()`を使ってみてください！

# 補足
上記のような`ボタンクリックイベント`から`リロードする`テストではない場合でも、少し待機して特定のメッセージの確認などを行いたい場面もあると思います。
そのような時も`pause()`ではなく`waitFor`メソッドを使うことで、無駄な待機時間をなくすことができます。

`waitFor`メソッドは**最長**どれくらい待機するかを指定することができます。
第一引数には対象のセレクタやテキストなどを指定し、第二引数に**最長で待ちたい秒数**を指定することができます。(指定しなければ最長5秒待ちます。)
ぜひ活用してみてください！

```php
// セレクタを最長5秒待つ
$browser->waitFor('@selector');
// セレクタを最長1秒待つ
$browser->waitFor('@selector', 1);

// テキストを最長5秒待つ
$browser->waitForText('Hello World');
// テキストを最長3秒待つ
$browser->waitForText('Hello World', 3);
```

# 参考
https://readouble.com/laravel/8.x/ja/dusk.html#:~:text=%E3%81%9F%E3%82%81%E3%80%81%E4%BE%BF%E5%88%A9%E3%81%AA-,clickAndWaitForReload,-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E4%BD%BF%E7%94%A8
【Laravel】特定の条件の場合のみバリデーションを行う

# はじめに
```php
$request->validate([
    'id' => 'required|digits_between:1,5',
    'name' => 'nullable|max:20'
]);
```
簡単なバリデーションを実装してみました。内容は以下の通りです。
1. `id`は必須であり、整数で1桁から5桁の間であること。
1. `name`はNULL許可であり、最大20字までであること。

このバリデーションの一部を**特定の条件の場合のみ行いたい**場合どうすればいいでしょうか。。

# パターン1 ： sometimesメソッドを使う

`Laravel`の`Validtor`インスタンスで`sometimes`メソッドを使用すると、条件付きでバリデーションを行うことができます。

https://readouble.com/laravel/9.x/ja/validation.html#complex-conditional-validation:~:text=Validator%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%A7-,sometimes%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89,-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D

```php
$validator = Validator::make($request->all(), [
    'id' => 'required|digits_between:1,5',
    'name' => 'nullable'
]);
$validator->sometimes('name', 'max:20', function ($request) {
    return in_array($request->id, [1, 2, 3, 4, 5]); 
});
```
`sometimes`メソッドには、**条件付きでバリデーションするフィールド名**、**追加するルール**、**条件となるクロージャ**の3つの引数を渡します。
第3引数のクロージャが`true`の場合、第1引数のフィールドに、第2引数のルールを追加します。
上記の例では、`$request->id`が1〜5の場合、`name`に`max:20`のルールを追加する処理となります。

# パターン2 ： 三項演算子を使う
三項演算子を使って、条件が`true`の場合のみルールを追加します。
```php
$rules = [
    'id' => [
        'required', 
        'digits_between:1,5'
    ],
    'name' => [
        'nullable', 
        in_array($request->id, [1, 2, 3, 4, 5]) ? 'max:20' : ''
    ]
];
$validator = Validator::make($request->all(), $rules);
```
`Validator::make`の第2引数に渡すルールを作る際に、三項演算子を使います。
`$request->id`が1〜5の場合は`max:20`を、そうでない場合は空文字を返す三項演算子を、`name`のルールに追加することで、パターン1と同じ条件を作ることができました。

# まとめ
場合によっては複雑な条件でバリデーションを行いたいことも良く出てくると思うので
今回のような方法も活用していきたいと思います。参考になれば幸いです。
【Swift】enumの値をランダムで返す

# はじめに
enumで定義した値をランダムで取得したい時の方法です。

# 実装
```swift
enum Sample: Int, CaseIterable {
    case one = 0
    case two = 1
    case three = 2
    
    static func random() -> Sample {
        Sample(rawValue: Int.random(in: 0...Sample.allCases.count)) ?? .one
    }
}
```

# 使い方
```swift
print(Sample.random())
```

# おわり
enumをIntに準拠させて、`Int.random`を使ってenumをランダムに取得します
7セグをデジタル時計にするPythonコード

## 1. はじめに

本記事では、弊社のAD7SGPR USBコンパクト7セグディスプレイ「Nanapo」をデジタル時計として使用するためのPythonを公開します。社内の人間がコーディングしてくれました。

AD7SGPRは、シリアル通信で文字列を送るだけで値を表示できる7セグメントディスプレイです。そのためシリアル通信可能なWEBアプリやターミナルソフトから制御が可能です。
あまりハードのことを考えずに7セグの制御が可能です。
<img src="https://github.com/bit-trade-one/AD7SGPR/assets/85532743/12f146fd-c330-4e64-a72a-60c566ce7d9e"
        alt="AD7SGPR接続系統図" width="420px">


## 2. 必要なモジュール

今回使用するPythonのモジュールは以下の2つです。

- `serial`: シリアル通信を行うためのモジュールです。
- `time`: 時刻を取得・制御するためのモジュールです。

これらは標準のPythonライブラリに含まれているため、特別なインストールは必要ありません。

## 3. Pythonコード

以下が今回の主役、デジタル時計を制御するPythonのコードです。

```python
import serial
import time

# AD7SGPRのシリアルポートを開く
com = serial.Serial('COM12', 115200)

while True:
    # 現在時刻を取得
    current_time = time.strftime('%H:%M:%S\n')

    # AD7SGPRに現在時刻を送信
    time_data = current_time.encode('ascii')
    com.write(time_data)

    # データが待っていれば一斉に読み込む
    dummy = com.read_all()
    print(dummy.decode('ascii'))  # データをデコードしてプリント

    # 1秒待機
    time.sleep(1)

# シリアルポートを閉じる
com.close()
```

注意すべき点として、`serial.Serial`で指定するシリアルポート（上記コードでは'COM12'）は、使用する環境により変更してください。

## 4.動作の様子
![20230728_110825.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605138/c58ce139-df92-976b-dd01-218639605270.gif)

Thonny4.0.2、
AD7SGPRファームウェアバージョン1.1で動作を確認しました。

## 5. まとめ

PythonとNanapoを用いて自作のデジタル時計を作る方法について解説しました。本コードを参考に様々な使い方をしていただけますと幸いです。
ほかにもWEBのAPIを絡めた表示ソフトのサンプルやNanapo自体のファームウェアも掲載しているためGitHubを覗いてみてください。
[・AD7SGPRのGitHub](https://github.com/bit-trade-one/AD7SGPR)
ソースコードコメント　オフショア

こんにちは、
今日またコメントについて話させてください。

昔、オフショア会社で1年ほどBrseとして働いたことがあります。開発はベトナムのチームと日本のチームがありました。入社したばかりの私が気づいたのは、ベトナムのチームがソースコードにあまりコメントをしていなかったことです。日本のチームも必ずしも丁寧にコメントを書いているわけではないですが、ベトナムのチームはほぼコメントがない。そして、上司と話しました。

    僕   ：　ベトナムの方のソースコードが全くコメントしてないですが。それは前から決まったのか
    上司 ：いいえ、違います。コメント書かないルールなんて決まってないですよ。
        当然絶対コメントしないといけないルールもないです。
    僕   ：そうですね。 複雑なコードも多いのですが、コメントなしソースコード理解しづらいですね。
    上司 ：そうなんですね。課題にしてみんなと相談しましょう。



やっぱり、みんなが最低限でもバッグ修正履歴、注意点などのコメントぐらいは必要と思いました。そして、コメントをする場合について以下のような質問がありました。

- 同じ言語で書くのか？それとも母語を使うのか？
- 同じ言語使ったら、英語、日本語どっちですか？（日本チームはベトナム語全然しらないので、ベトナム語は絶対ない）


ちょっと違うですが、昔、タイのチームと仕事をしたことがあります。その時に、日本側が日本語で、タイ側は英語でコメントしました。やっぱり母語でコメントした方が書く人には一番いいですね。そして、ちゃんとわかりやすい、誤解ないコメントができます。
日本のチームも英語読むぐらいは翻訳ツール使ったらなんとかできる。タイ側も日本語できるメンバが一人居て、それとも翻訳ツールでちゃんと日本語のコメント理解できました。
確かに翻訳もちょっと時間かかりましたが、ソースコードを全て理解できないときがあります。そういうときにコメントがあると本当に助かります。

オフショアで、言語の壁が原因でコメントについて様々な問題がありますが、
それについて、私が理解したことは：
- わかりやすいソースコードで言語の壁を乗り越えられます。
- 問題から逃げずに、コメントをしっかりと書いてください。
React-router-dom で画面遷移時にスクロール位置をリセットする

react-router-dom を使って実装していた際、スクロールした状態で画面遷移をすると遷移前のスクロール位置がそのまま残り、遷移後も画面がスクロールされた状態で表示されてしまう事象を解決した際の備忘録です。

## 環境
``` package.json（抜粋）
{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.14.2",
  },
}
```

## 方法
``` Page.jsx
export const Page = () => {
    // 画面遷移した際に、スクロール位置をリセット
    window.scrollTo({top: 0, behavior: "instant"});

    return(
    <>
        ...省略...
    </>
    );
}
```
最初は「`useHistory`などを使用して難しいことしないといけないのかも...？」と悩んでいましたが、単純に`window.scrollTo({top: 0, behavior: "instant"});`を実行することで解決しました。
今回は、この方法でシステム要件を満たすことができたのでOKにします。
hamlテンプレートを使おう

# hamlとは
hamlとはHTMLをより簡単に、綺麗にすることができるテンプレートエンジンのこと。

「HTML avstraction markup langage」の略称で、直訳すると『HTMLを抽象化したマークアップ言語』という意味です。

Rubyと共に使うことができ、hamlで書いたプログラムはhtml.erbに変換されます

# hamlを導入する
Gemfileにて、`hamlit`と`erbhaml2`をインストールできるようにします
```ruby:Gemfile
:
gem 'hamlit'
:
```
```ruby:Gemfile
group :development do
    :
    :
    gem 'erbhaml2'
end
```

そしてコマンドで`bundle`をインストールします
```
$ bundle install
```
# html.erbをhamlに変換する
コマンドで以下を実行します
```
$ bundle exec rake html:replace_erbs
```
これで、**view**ファイルを見ると、**html.haml**に変換されています
Apple、セルフサービス修理をiPhone 14 M2 MacBookまで拡張

![Apple Extends Self-Service Repair to iPhone 14 M2 MacBooks.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518189/fa2957f2-260f-eb4e-5024-7c2f731d66c6.jpeg)

Appleは、6月21日にセルフサービス修理プログラムを現在のiPhone 14ラインナップと、13インチMacBook AirとM2搭載MacBook Proを含む追加のMacモデルに拡大すると発表した。

この拡張により、電子機器の修理経験のある個人は、Apple Store や正規サービスプロバイダーが使用するものと同様の、Apple の公式パーツ、ツール、マニュアルにアクセスできるようになります。

2022 年 4 月以降、セルフサービス修理により、電子デバイスの修理経験のある人は誰でも、Apple Store や Apple 正規サービスプロバイダーで使用されているのと同じマニュアル、Apple 純正部品、ツールにアクセスできるようになりました。
![QQ图片20230728162701.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518189/9b864506-6b2c-82f9-1ae2-79dfb9ccebeb.jpeg)

6 月 21 日より、iPhone 14 の各モデル、M2 13 インチ MacBook Air、M2 Pro MacBook Pro、および M2 Max MacBook Pro がセルフサービス修理プログラムの一部となりました。これらのデバイスを修理したい人は誰でも、Apple Store や正規サービスプロバイダーが使用しているものと同じ部品、iPhone 修理ツール、マニュアルを使用できます。

全員向けではありません
Appleはまた、iPhone 12およびiPhone 13のTrue Depthカメラとトップスピーカー、およびM1 Macデスクトップのセルフサービス修理プログラムを米国、ベルギー、フランス、ドイツ、イタリア、ポーランド、スペイン、スウェーデンで拡大すると発表した。 、そしてイギリス。
![QQ图片20230728163027.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518189/eda531ee-7a5a-7a52-891d-6481fbdc20bf.jpeg)

Apple はまた、使いやすくするためにシステム構成プロセスを更新すると発表しました。これは、修理後に Apple 純正部品を認証し、必要なファームウェアのアップデートを行い、最大のパフォーマンスを確保するために部品を調整するために実行されるソフトウェア ツールです。
![QQ图片20230728163035.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518189/bd9955bf-a09b-ab92-519b-db42c5cba834.jpeg)

Apple では、システム コンフィギュレータで修理を完了するためにユーザーがセルフサービス修理サポートに連絡する必要がなくなりました。より専門的な携帯電話修理ツールが必要な場合は、China Phonefix が最適です。

Appleは最近、今月初めのWWDCで最新のiOSおよびMacOSソフトウェアと、新しい複合現実ヘッドセットであるApple Vision Proを発表した。次の大きなイベントは、次期iPhone 15の発表が予定されている秋に開催される可能性が高い。
Reactで画像アップロード機能を作成する

# はじめに
タイトル通り。
reactとtypescriptで、投稿フォームに画像をアップロードする機能を実装したので、サンプルを掲載します。

# 仕様
- 「画像アップロード」ボタンを押すと、ファイルエクスプローラーを開く。
- 選択した画像がプレビュー表示される。
- 「投稿する」ボタンを押すと、画像が保存される。←すなわち、画像を送信する際は二段階の手順を踏む必要がある。（「画像アップロード」ボタン→「投稿する」）「投稿する」ボタンを押しただけでは画像データを送信できないため、工夫が必要。（今回は`FormData`を使用）
- 画像アップロードをキャンセルできる。

# 結論のコード
```Form.tsx
import React, { useState, useContext } from 'react'
import { useForm } from 'react-hook-form'

import { createPost } from '../../api/api_actions'
import { Post } from '../../interfaces/interface'

export const Form = () => {
  const { register, handleSubmit, formState: { errors } } = useForm<Post>()
  const [isFileTypeError, setIsFileTypeError] = useState<boolean>(false)
  const [photo, setPhoto] = useState<File>()
  const [preview, setPreview] = useState<string>("")

  const emptytarget: React.MouseEventHandler<HTMLInputElement> = (event) => {
    event.currentTarget.value = ''
  }

  const handleFile: React.ChangeEventHandler<HTMLInputElement> = async(event) => {
    if (event.target.files === null || event.target.files.length === 0) {
      return
    }
    setIsFileTypeError(false)

    const file = event.target.files[0]

    if (
      ![
        "image/jpeg",
        "image/png",
        "image/jpg"
      ].includes(file.type)
    ) {
      setIsFileTypeError(true)
      return
    }

    setPhoto(file)
    setPreview(window.URL.createObjectURL(file))
  }

  const onSubmit = async(data: Post) =>{

      const formData = new FormData()
      formData.append("post[image]", photo)

      try {
        const res = await createPost(formData as any)
        if (res.status === 200) {
          console.log('投稿に成功しました')
        } else {
          console.log(res.data.message)
        }
      } catch (err) {
        console.log(err)
      }
    }

  const canselFile = () => {
    setIsFileTypeError(false)
    setPhoto(undefined)
    setPreview("")
  }

  return(
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
          <p>画像</p>
          <p>（ファイル形式はjpeg, png, jpgのみアップロード可能です。）</p>
          <label htmlFor="photo">
            画像アップロード
            <input hidden type="file" id="photo" name="photo" accept="image/*,.png,.jpg,.jpeg" onChange={handleFile} onClick={emptytarget}/>
          </label>

          {
            isFileTypeError && (
            <div>
              <span>※jpeg, png, jpg以外のファイル形式は表示されません。</span>
            </div>
          )}
              
          <br/>
          {
            preview ? (
              <div>
                <p>投稿画像イメージ</p>
                <img src={preview} alt="preview img" />
              </div>
            ) : (
              null
            )
          }
          <br/>
          <button type="submit">投稿する</button>
      </form>
      <button type="submit" onClick={canselFile}>画像リセット</button>
    </div>
  )
}
```

# 補足説明
- 画像アップロード機能について
  - 「画像アップロード」ボタンを押すと、`emptytarget`と`handleFile`が起動する。
  -  `event.target.files[0]`で送信した画像データを取得できる。
  -  変数`photo`に画像データを入れ、フォーム投稿時まで保持しておく。
  -  画像はURLにしてimgタグでプレビュー表示する。そのため、`createObjectURL`によって、画像データを一意のURLに変換している。

- 画像投稿機能について
  - `FormData`を使い、`photo`で保持する画像データを送信するデータに付け加える。

# 参考
https://ja.javascript.info/formdata
秋月ST7789(ATM0130B3(SPI))でデモる(Arduino UNO)(部品リスト)


秋月ST7789(ATM0130B3(SPI))でデモる(Arduino UNO)

↓ここをクリック↓

https://qiita.com/caa45040/items/b070ec14ee8003c54ed2

↑ここをクリック↑

---------------------------------------------------

![o_cop635.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/376b7880-9684-d440-cf1f-63f72e392635.jpeg)



その互換機
Ａｒｄｕｉｎｏ　Ｕｎｏ　ＳＭＤ　Ｒｅｖ３
[A000073]
通販コード　M-07383
発売日　2014/02/27

![o_cop626.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2b635e24-eea2-bfe6-6274-fb3f4fa342c9.jpeg)



ＡＴＭ０１３０Ｂ３使用フルカラー液晶コントロールキット
[AE-ATM0130B3]
通販コード　K-15560
発売日　2020/11/12

![o_cop627.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a9134ce9-f309-42b9-1ae1-bef41dd1304c.jpeg)



片面ガラス・薄型ユニバーサル基板Ｃタイプ（７２×４８ｍｍ）めっき仕上げ（日本製）
通販コード　P-04718
発売日　2011/04/15

![o_cop628.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2b6ab571-a6bc-3590-fc67-6e1066d876a1.jpeg)



Ｌ型ピンソケット　１×１０（１０Ｐ）
[FH-1x10RG]
通販コード　C-12984
発売日　2018/03/20

![o_cop630.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ec70006e-7458-cee4-ced0-49ca49979329.jpeg)



ブレッドボード・ジャンパーワイヤ（オス－オス）セット　各種　合計６０本以上
[BBJ-65]
通販コード　C-05159
発売日　2011/09/19

![o_cop629.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/593a751c-2f67-f129-fada-c3974bd4142b.jpeg)


ダイソー接着剤
香川全完達成人数一覧

AtCoderで香川全完達成人数を調べました。ここではペナを含めずに60分以内に全完した人とします。(ぴったりも)

# ABC212〜


| コンテスト | 人数 | 最高Diff |
|---------|-----|----|
| ABC212 | 4 | 2741 |
| ABC213 | 2 | 2806 |
| ABC214 | 2 | 3138 |
| ABC215 | 2 | 3101 |
| ABC216 | 2 | 3295 |
| ABC217 | 13 | 3112 |
| ABC218 | 3 | 2805 |
| ABC219 | 0 | 3297 |
| ABC220 | 1 | 3047 |
| ABC221 | 0 | 2914 |
| ABC222 | 1 | 3477 |
| ABC223 | 2 | 2771 |
| ABC224 | 1 | 2887 |
| ABC225 | 2 | 3061 |
| ABC226 | 2 | 2813 |
| ABC227 | 1 | 3229 |
| ABC228 | 8 | 2729 |
| ABC229 | 2 | 3308 |
| ABC230 | 0 | 3528 |
| ABC231 | 10 | 2681 |
| ABC232 | 1 | 2780 |
| ABC233 | 11 | 2530 |
| ABC234 | 17 | 2505 |
| ABC235 | 4 | 2967 |
| ABC236 | 5 | 2898 |
| ABC237 | 6 | 2807 |
| ABC238 | 4 | 3247 |
| ABC239 | 9 | 2686 |
| ABC240 | 2 | 3184 |
| ABC241 | 2 | 2881 |
| ABC242 | 4 | 2835 |
| ABC243 | 0 | 3884 |
| ABC244 | 2 | 2878 |
| ABC245 | 1 | 3057 |
| ABC246 | 6 | 2677 |
| ABC247 | 11 | 2664 |
| ABC248 | 3 | 2960 |
| ABC249 | 0 | 3487 |
| ABC250 | 2 | 2773 |
| ABC251 | 2 | 3108 |
| ABC252 | 4 | 3015 |
| ABC253 | 9 | 2758 |
| ABC254 | 3 | 2890 |
| ABC255 | 2 | 2734 |
| ABC256 | 14 | 2531 |
| ABC257 | 0 | 3461 |
| ABC258 | 7 | 2708 |
| ABC259 | 16 | 2428 |
| ABC260 | 0 | 3339 |
| ABC261 | 2 | 2803 |
| ABC262 | 0 | 3114 |
| ABC263 | 3 | 3041 |
| ABC264 | 4 | 2660 |
| ABC265 | 0 | 3319 |
| ABC266 | 8 | 2865 |
| ABC267 | 12 | 2561 |
| ABC268 | 9 | 2560 |
| ABC269 | 2 | 3178 |
| ABC270 | 2 | 3159 |
| ABC271 | 4 | 2908 |
| ABC272 | 0 | 3740 |
| ABC273 | 0 | 3598 |
| ABC274 | 4 | 3191 |
| ABC275 | 0 | 3210 |
| ABC276 | 1 | 3087 |
| ABC277 | 3 | 2917 |
| ABC278 | 0 | 3768 |
| ABC279 | 3 | 3279 |
| ABC280 | 0 | 3307 |
| ABC281 | 4 | 3180 |
| ABC282 | 11 | 2621 |
| ABC283 | 15 | 2682 |
| ABC284 | 3 | 3125 |
| ABC285 | 1 | 3192 |
| ABC286 | 11 | 2526 |
| ABC287 | 11 | 2639 |
| ABC288 | 1 | 3282 |
| ABC289 | 2 | 3246 |
| ABC290 | 0 | 3569 |
| ABC291 | 50 | 2176 |
| ABC292 | 20 | 2340 |
| ABC293 | 2 | 2831 |
| ABC294 | 2 | 3058 |
| ABC295 | 3 | 2728 |
| ABC296 | 5 | 2822 |
| ABC297 | 6 | 2855 |
| ABC298 | 4 | 2808 |
| ABC299 | 4 | 2997 |
| ABC300 | 6 | 3209 |
| ABC301 | 0 | 3262 |
| ABC302 | 25 | 2407 |
| ABC303 | 5 | 2736 |
| ABC304 | 1 | 3177 |
| ABC305 | 0 | 3344 |
| ABC306 | 1 | 3335 |
| ABC307 | 4 | 2754 |
| ABC308 | 1 | 2861 |
| ABC309 | 6 | 3029 |
| ABC310 | 1 | 3343 |
| ABC311 | 0 | 3605 |
ダッシュボード機能のカスタムHTMLを使ってみた

# 概要
7/28にリリースされた新機能「ダッシュボード」のカスタムHTMLで外部サイトの内容を埋め込みます。
今回はMetabaseで作成したグラフを埋め込んでみます。

# ダッシュボード機能
プリザンターに待望のダッシュボード機能が追加されました。
テーブルやフォルダへのリンク集を作る「クイックアクセス」、最新情報を表示する「タイムライン」、マークダウン形式で文章を表示する「カスタム」、そしてHTML形式で様々な表現ができる「カスタムHTML」という４つのパーツを自由に組み込むことができます。  
詳しくは[オンラインマニュアル](https://pleasanter.org/manual/dashboard)を参照ください。

https://pleasanter.org/manual/dashboard

# ダッシュボードに表示するグラフの作成
今回はダッシュボードにグラフを表示します。グラフはOSSのBIツールである[Metabase](https://www.metabase.com/)を利用します。

https://www.metabase.com/

実はMetabaseを触るのが今回初めてでしたので、以下にMetabaseの準備からプリザンターとの連携、グラフ作成までの手順を簡単に記載します。

## Meatabaseの準備
Metabaseの環境準備方法はいろいろありますが、今回はローカルPCでDockerイメージを取得し起動します。
https://www.metabase.com/start/oss/ に記載しているコマンド
```
docker run -d -p 3000:3000 --name metabase metabase/metabase
```
を実行し、起動出来たら http://localhost:3000 にアクセスします。ユーザ登録画面が出ますので、登録完了すると以下画面が表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/d5da92a1-568d-b20c-c69a-e23ca8d1b690.png)

## Meatabaseとプリザンターの連携
今回グラフを作成するデータはプリザンター側に準備しますので、MetabaseにてでプリザンターのDBに対する接続設定を行います。
画面右上の歯車アイコンから「管理者設定」－「データベースを追加する」をクリックし、DB接続情報を入力します。
設定に成功すると「データの閲覧」からプリザンターのテーブル一覧が表示できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/81ed617a-3994-16d6-e311-f0e7df66c9c2.png)

## データ準備
プリザンター側でグラフ用のデータを作成します。今回は製品種類、売上日、売上数を管理するようなテーブルを記録テーブルで作成し、データを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/c03ed0e9-c57b-cc03-4e1f-a4bd7b7a473c.png)

## Metabase側でデータ抽出
Metabaseの右上の「+ New」をクリック、「SQLクエリ」を選択します。データベースを選択後、下記のように記録テーブル（Results）から必要な項目を抽出したselect文を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/4168d75c-26ab-f52b-92dc-1f5e253dfa97.png)
select結果が表示したら、画面下部のグラフアイコンをクリックするとグラフが表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/2476f32f-4340-bc48-29ef-0a744155f194.png)
画面上部の「+ 探索結果」をクリックし、「フィルター」で売上日で「現在の月」を指定すると、下図のように範囲を絞り込んだグラフが完成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/d4258ffd-46d6-b334-5e91-e189c7a671a3.png)
画面右下の「共有」アイコンをクリックし、「公開埋め込み」のスニペットをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/457c9c43-ed57-4571-1e8b-5277287722d7.png)


# ダッシュボードへの埋め込み
プリザンターでマニュアルを参照しながらダッシュボードを作成し、「カスタムHTML」パーツを追加します。
カスタムHTMLの詳細設定で、「内容」欄に先ほどコピーしたスニペットを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/49a5034a-080e-0ada-83c6-1fcabe32c1fc.png)


ダッシュボードを開く下記のようにMetabase側のグラフが表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314422/b4398991-1610-15ff-ba74-ab18e728d1f2.png)
グラフの高さ、幅はスニペットにあるwidthとheightで調整可能です。

# まとめ
ダッシュボードのカスタムHTMLを使用すると、スクリプトを一切書かずにMetabaseのグラフを表示することができました。他にもyoutubeやGoogleMapなどの内容も同様の手順で埋め込むことができます。[※1](#notice)
ダッシュボード機能が追加になったことで、より皆様のニーズにこたえられる製品になったと思いますので、ぜひ使ってみてください。

<a href="#notice"></a>

:::note warn
注意 
※1 youtubeやGoogleMapの利用規約に違反しないよう注意してください。自己責任でお願いします。
:::
GitHub Actions で pytest の失敗箇所をコード中にインライン表示する

GitHub Actions にはテストなどの実行結果を、Pull Requestのコード上にアノテーションされた形で表示する機能があります。Node.js などではこれが自動で行われることがあるためご存知の方も多いかもしれませんが、Pythonでも上手く活用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/047d9217-6cc5-2d14-446b-e257a0fa4fb4.png)

## pytest の結果をコード上に表示する

実は Pytest が公式にそのためのプラグインを提供しています。これをインストールした状態で GitHub Actions で pytest を実行するだけで機能します。

https://github.com/pytest-dev/pytest-github-actions-annotate-failures

具体的には、以下のようにインストールしておけばいいでしょう。

```bash
# pip でインストールする場合
pip install pytest-github-actions-annotate-failures

# Poetry に含めておく場合
poetry add -G dev pytest-github-actions-annotate-failures@latest
```

あとは GitHub Actions 上でふつうに `pytest` を実行するだけです。pytest実行時のコマンドラインオプションを変更したりする必要もありません。カンタン。

## Ruff の結果もインライン表示できる

Flake8 を置き換える Python 用 Linter として、Ruff というものが有名になっています。

https://github.com/astral-sh/ruff

[GitHub ActionsのPython用チュートリアル](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#using-the-python-starter-workflow) もいまや Flake8 のかわりに Ruff を用いています。

GitHub Actions で Ruff を実行する際に `--format=github` オプションを付与しましょう。GitHub のアノテーション機能が検出できる形式で Ruff がエラーを出力してくれます。

```yaml
      - name: Lint with Ruff
        run: poetry run ruff --format=github .
```
[AWS Q&A 365][AppSync]AWSのよくある問題の毎日5選 #100

# 1. AWS AppSyncは、顧客データのセキュリティを確保するためにどのような対策を講じていますか？
回答: AWS AppSyncは、データの静止時および転送時の暗号化、AWS Identity and Access Management (IAM) および Amazon Cognitoを利用した細かなアクセス制御、AWS Shieldを用いた一般的なWeb攻撃からの保護など、多数のセキュリティ機能を提供しています。

# 2. AWS AppSyncは、顧客が自身のデータへのアクセスを制御できますか？
回答: はい、AWS AppSyncは、IAMおよびAmazon Cognitoを通じた細かなアクセス制御で、顧客が自身のデータへのアクセスを制御できます。顧客は、カスタム認証および承認メカニズムも使用できます。

# 3. 顧客は自分の暗号化キーをAWS AppSyncと共に使用できますか？
回答: はい、顧客は自分の暗号化キーをAWS AppSyncと共に使用できます。AWS AppSyncは、静止時の暗号化のためにAWS Key Management Service (KMS)をサポートしており、顧客は自身の暗号化キーを作成および管理できます。

# 4. AWS AppSyncは、ログ取得および監査機能を提供しますか？
回答: はい、AWS AppSyncは、CloudWatch LogsとCloudTrailを通じてログ取得および監査機能を提供します。顧客はAPIリクエストとレスポンスを監視およびログ記録し、リソースへの変更を追跡できます。

# 5. AWS AppSyncはDDoS攻撃に対してどのように保護しますか？
回答: AWS AppSyncは、追加料金なしで提供されるAWS Shield Standardを使用してDDoS攻撃から保護します。AWS Shield Standardは、DDoS攻撃の自動検出と緩和を提供します。顧客は、より高度な保護のためにAWS Shield Advancedを使用することもできます。
[AWS Q&A 365][AppSync]Daily Five Common Questions #100

# 1. What measures does AWS AppSync have in place to ensure the security of customer data? 
Answer: AWS AppSync provides multiple security features such as encryption at rest and in transit, fine-grained access control with AWS Identity and Access Management (IAM) and Amazon Cognito, and protection against common web attacks with AWS Shield. 

# 2. Does AWS AppSync allow customers to control access to their data? 
Answer: Yes, AWS AppSync allows customers to control access to their data with fine-grained access control through IAM and Amazon Cognito. Customers can also use custom authorization and authentication mechanisms. 

# 3. Can customers use their own encryption keys with AWS AppSync? 
Answer: Yes, customers can use their own encryption keys with AWS AppSync. It supports AWS Key Management Service (KMS) for encryption at rest, which allows customers to create and manage their own encryption keys. 

# 4. Does AWS AppSync provide logging and auditing capabilities? 
Answer: Yes, AWS AppSync provides logging and auditing capabilities through CloudWatch Logs and CloudTrail. Customers can monitor and log API requests and responses, and track changes to their resources. 

# 5. How does AWS AppSync protect against DDoS attacks? 
Answer: AWS AppSync provides protection against DDoS attacks with AWS Shield Standard, which is included at no extra cost. AWS Shield Standard provides automatic detection and mitigation of DDoS attacks. Customers can also use AWS Shield Advanced for more advanced protection.
TypeScript初心者必見！ジェネリクスの理解を深めよう



こんにちは！今回はTypeScriptの重要な概念であるジェネリクスについて解説していきます。ジェネリクスは型の問題を解決する強力なツールであり、型の安全性を維持しながらコードの再利用性と柔軟性を高めます。

## 1. ジェネリクスって何？

ジェネリクスとは、型システムの一部で、クラスや関数に柔軟性を持たせるためのツールです。ジェネリクスを使用することで、型情報（つまり、どのようなデータがコードに渡されるのか）を保持しながら、コードを抽象化・再利用することが可能になります。

例えば、次のようなジェネリック関数を考えてみましょう。

```typescript
function identity<T>(arg: T): T {
    return arg;
}
```

この関数は、型を指定して呼び出すことができます。

```typescript
let output = identity<string>("myString");
console.log(output);  // "myString"
```

また、型推論を利用して引数から型を自動的に推論することも可能です。

```typescript
let output = identity("myString");
console.log(output);  // "myString"
```

## 2. ジェネリクスのメリット

ジェネリクスのメリットは、型の安全性の維持、コードの再利用、自己文書化にあります。

### 型の安全性

ジェネリクスを使用すると、関数やクラスが動作する型を制限することなく、コードを抽象化できます。これにより、コンパイル時に型安全性を保つことができます。

例えば、以下のジェネリック関数`getArrayItems`は、任意の型の配列を引数に取り、その配列をそのまま返します。この関数は数値の配列、文字列の配列、オブジェクトの配列など、どのような型の配列に対しても使用することができます。

```typescript
function getArrayItems<T>(arr: T[]): T[] {
    return arr;
}

let numArray = getArrayItems<number>([1, 2, 3, 4]);  // number[]
let strArray = getArrayItems<string>(['a', 'b', 'c']);  // string[]
let objArray = getArrayItems<{ id: number }>([{ id: 1 }, { id: 2 }]);  // { id: number }[]
```

### コードの再利用

ジェネリクスを使用すると、特定の型に依存せずに関数やクラスを設計できます。これにより、さまざまな型で動作する一般的なコードを作成できます。

例えば、以下の`GenericNumber`クラスは、`number`型で動作するバージョンと`string`型で動作するバージョンを同じコードで作成することができます。

```typescript
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myNumber = new GenericNumber<number>();
myNumber.zeroValue = 0;
myNumber.add = function(x, y) { return x + y; };

let myString = new GenericNumber<string>();
myString.zeroValue = "";
myString.add = function(x, y) { return x + y; };
```

### 自己文書化

ジェネリクスは、関数やクラスがどのような型で動作するかを示すため、コードの可読性を向上させます。これにより、他の開発者がコードを理解しやすくなります。

## 3. ジェネリクス vs any

`any`型とジェネリクスの違いは、型の安全性を保つかどうかです。`any`型を使用すると、型の安全性が犠牲になる可能性があります。一方、ジェネリクスを使用すると、型の安全性を保ったままコードの再利用性と柔軟性を高めることができます。

```typescript
let myVariable: any = 'Hello';
myVariable = 10;  // no error, but potentially unsafe!

function identity<T>(arg: T): T {
    return arg;
}
let output = identity<string>("myString");  // output is of type string
```

以上のように、ジェネリクスはコードの柔軟性と再利用性を高め、型の安全性を保つための強力なツールです。一般的には可能な限りジェネリクスを使用し、型の安全性を保つことが推奨されます。

---

以上、TypeScriptのジェネリクスについての解説を終わります。この記事がTypeScriptのジェネリクスについて理解を深める手助けになれば幸いです。より詳細な情報を得たい場合は、公式ドキュメントを参照してください。それでは、Happy Coding！
ソースコードコメント

# コメントとは
ソースコードは、人がコンピュータに動作を指示するためのものです。
ただしコメントは、人と人の会話です。
コメントで
 - コードに注釈や解説を追加すること
 - コードの論理や意図をより理解しやすくすること
 - バグ修正履歴を記したりする

# コメント利点
- 自分自身が何を書いたかをより理解することできる
- メンテナンスやアップグレードが容易
- 他のメンバーがコード理解しやすくなる
- エラーの特定やデバッグが迅速に行えるようになる

:::note info
ではコメントが当たり前じゃないですか？と思ってる人多いと思いますが。
実際はコメントしない人、コメントする必要ない人も結構います。
次のはこの話を細かく見てみましょう。
:::

# コメント反対派
コメントを書かない理由が次のようなものがあります：
- コードを読んで理解できない場合、書き直すべき
- コードが変更、コメント更新されず　→誤解を招く説明
- シンプルで、よく書かれたコードのコメントは、既に明らかなコード自体を複製
- コメントを書くことはあなたを遅くし、あなたが集中すべき主なこと、つまりコード自体


優れたコードは自己文書化するべきです。コードを読んで理解できない場合、そのコードは良くないので、書き直すべきです。変数やメソッドの名前の良好な選択、直接的なアルゴリズムなどがこのカテゴリに該当します。
コメントに依存するコードは、それらをクラッチとして使用しています。つまり、コード自体が複雑または構造が悪いため、書き直す必要があります。
コードが時間とともに変更されると、コメントはしばしば更新されず、同期が取れなくなります。古いコメントは、最初のコメントが書かれた時と比べて、コードが現在何をするのかを誤ったまたは誤解を招く説明を提供します。
シンプルで、よく書かれたコードのコメントは、既に明らかなコード自体を複製します。一例としては、シンプルなgetterメソッドがあります。「フィールドXを取得する」コメントは、この状況では冗長です。
コメントの品質は、プログラマーによって大きく異なり、ユニットテスト、コミット前のフック、自動化されたコード品質分析などの実行可能コードと同じ厳格さには受けていません
コメントを書くことはあなたを遅くし、あなたが集中すべき主なこと、つまりコード自体から焦点をそらします。

# コメント賛成派
コメントを書く理由以下のようなものがあります：
- 一般的にコードよりも読みやすく、早い
- ビジネスルール、プロセスを文書化
- ドキュメントに変換
- チームは、コードが複雑であっても、  コメントでコードを直接的に説明
- コメントを書くことは、思考の落とし穴と仮定を明らかにする
   2度考え一度はコード、コメント

コメントはコードの意図を明らかにします。 コードが明確でない場合、コメントはその目的をはるかに人間が読みやすい方法で明らかにします。

コメントはビジネスルールを文書化します。たとえば、コードが答えが42であると述べているかもしれませんが、なぜ答えが42であるのかをはっきりさせることはほとんどありません。
ビジネスはおそらく何らかのビジネス理論に基づいてこの決定を下しました。
そのため、それは持続的で、見つけやすく、誰もが不注意にルールを破るのを防ぐ場所で文書化するべきです。コメントはこの目的によく適しています。

コメントはプロセスを文書化します。前述のポイントと同様に、コードがプロセスまたは手順のシーケンスに従っている場合、各ステップとその依存関係をより人間に優しいフォーマットで説明するのは簡単です。

Javadoc、JSDocなどの生成。メソッド、フィールド、クラスに配置されたコメントは、
Web上で読むことも、IDEからアクセスすることもできるHTMLドキュメントに変換できます。
よく文書化されたコードは、ソースコードの中をのぞき見ることなく（これは容易にセーターの端から糸をほどくようなものになります！）、
自信を持って使用できるブラックボックスになります。
これはAPIに特に便利であり、よく文書化されていてフォローしやすいAPIやライブラリを使用したことがあり、他のものはそれほどではなく、
掘り下げて探し、探し回ることが必要で、いらいらしながら多くの時間を費やすことが必要です。

コメントは一般的にコードよりも読みやすく、早い。
チームは、コードが複雑であっても、よく書かれたコメントを頼りにして、コードを直接的に説明できます（先の可読性に関する議論は素晴らしい例です）。
コメントを書くのが遅いという反対面は、大抵の場合、それらは付随するコードを読むよりもはるかに早く読むことができます。

:::note info
**逆の立場になって初めてわかること**
私はソースコードコメント書く派なんですが、反対派の意見から「コメントはいつでも必要なんですか」、「どんなコメントがいいですか」いろいろ考えました。
:::

# Good comment ≠ Good code
プログラマは最終的に良いソースコード書く必要なんです。コメントとソースを比べるとソースの方が大事と思います。
コメントでソース理解でよければ良いソースではなく、良いソースコードを書いて、コメントが必要なだけ追加したらいいです。
例：

![comment_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3505194/bf8dbb7c-eb20-2c9f-edeb-21de2cb04fa0.png)

上記のコードは、コメントでソースの流れ、何するのかを明確しました。それは良いコメントですよね。（コメントないと何してるのかちょっと理解しにくい）
では、これは良いソースコードですか？というと、答えは**いいえ**
簡単な列なので、たぶんすぐわかると思いますが。このソースの問題は**変数名が無意味**です。
以下のように変数名編集したら、確かに、ソース自体がめっちゃわかりやすい感じました。
そして、上記のコメントも必要なくなります。すばらしいいいい
![comment_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3505194/c4f98120-bef0-3776-2d1f-194c294c9bda.png)


# 結論
- ソースコメントはプログラミングにおいて良い習慣、やってほしい
- いいコメント書くより、とりあえず、良いソースコード書いてください
- ...

「どんなコメントが良いのか」「どんなコメントが悪いのか」などコメントについて話がまだまだいっぱいあるですが、
次回話しましょう。((´∀｀))
[備忘録] .pngを.SVGに変換する際の注意点

# はじめに
<!-- 発端や概要を記載 -->
HTMLで.pngを.svgに変換して表示しようとしたときにうまくいかなかったので、解決法を備忘録として残します。
変換にはillustratorを使用しました。

## 原因
.pngファイルを書き出して.svgに変換していた
<a id="#Chapter1"></a>
## 解決法
書き出すだけではだめで、配置した.pngを画像トレースしてから、.svgで書き出す必要があった。
新しい言語のキャッチアップはTODOアプリを作るのが最短だと転職して気づいた

# はじめに

`Uzabaze,Inc.`に入社して半年が経とうとしています。
ユーザベースではマイクロサービス、マイクロフロントエンドを導入しており、小さい単位でシステムを構築しています。
会社の風潮として小さなシステム単位で技術選定ができる、新しい技術に挑戦ができるので日々様々な技術に触れています。

☆ 入社前のスキル
`Rails(Ruby)` `Python` `React` `Vue` `TypeScript` `Go`

↓

☆ 入社後半年のスキル
`Kotlin` `Java` `Rust` `F#` `Rails(Ruby)` `Python` `React` `Vue` `TypeScript` `Go` 

と新しい言語が色々できるようになりました

ここで、色々な言語をキャッチアップしている中で自分なりに`最短`だと思うような方法が固まってきたのでまとめていきます。

# 最短で学ぶ方法

## 1. いきなり開発を行う

一番効率の良い方法は`いきなり何かを開発`することです。

多くの方は本を読んだり、ドキュメントを読んだりして言語特有の機能や文法などを学んでから開発を進めることが多いと思います。私もその言語に関する本を3冊以上やってから学習していました。
これでは本を読んで実装する時間がとにかくかかり最短ではないです。

`いきなり開発なんてできないよ`と思うのではないでしょうか。
やり方がわかれば可能です

こちらについてはこのあと説明します。

本を読んで学習してから開発をしようが、いきなり開発しようが躓くところは変わらないと思います。
結局何かを参考にするので、それならいきなり開発したほうが効率が良いです。

## 2. プログラミングに慣れる

新しい技術をキャッチアップするときに大事なのは、似たような技術を知っていることだと思います。
オブジェクト指向の言語を知っていれば、だいたいのオブジェクト指向言語は似ていますし、DIの考え方などもだいたい同じなのですばやくキャッチアップができます

また関数型言語も1つ何かしらやったことがあれば、ある程度キャッチアップは楽にできます

なのでもし時間や機会があるなら、手続き型以外にもやったことのないような言語を体験しておくのは良いかと思います

もしプログラミング初心者でなんの言語もやったことないというのであれば、`ゆっくり書籍を学ぶ`のが最初のやるべきことでプログラミングに慣れてからチャレンジすべきです

# 最短で学ぶための開発方法

`1. いきなり開発を行う`について詳しく説明します。
私は新しい言語やフレームワークを学ぶときに作るものが決まっています

それが`TODOアプリ`を作るです

いままでに多くのTODOアプリを作成しました。
TODOアプリは`CRUD`がすべて学べたり、フロントエンドでも必要となる基礎的な技術がおおよそ利用できる素晴らしい題材です。またいきなり知らない言語で開発してもシンプルなので短時間でできますし、参考とするリポジトリが新しい言語でも多くあります。

以下が私が半年で作ったTODOアプリです

https://github.com/jinwatanabe/rust-todo-clean-app

https://github.com/jinwatanabe/fs-todo-clean-app

https://github.com/jinwatanabe/go-todo-clean-app

TODOアプリを作ることで、短期間で技術のキャッチアップを行えますし、シンプルな構成になるので、リポジトリを1津用意しておけば`今後ずっと参考にしつづける`ことができます (どうやってDIするか、DBの設定するかなど)

TODOでなくてもよいのですが、難しいのを作ってしまうと最短で学習することができなかったり、完成しきれなかったりするので私はTODOを作ることにこだわっています (ロジックも考えなくて良い)

## 事前に学ばないでどう開発するのか

ここに関しては現代ならではの方法でキャッチアップをしながら開発を進めます。
それが

`ChatGPT`と`GitHub Copilot`です。

環境構築から始まり、だいたいのことは`ChatGPT`が教えてくれます。
またテストコードに関しては`Copilot`と公式サイトをみて書いていきます

9割くらいのコードがこれで学べます。
またよくわからない言語仕様などは、そのままChatGPTになげて理解するようにすることで最短でアプリが作れます

そもそも暗記などする必要はないので、教えてもらったことを理解しながら実装して、サイド実装するときにTODOアプリを参考にして難しいアプリを作れば良いと思います

## 他人のリポジトリを参考にする

`これが個人的に学習時間を最短にしていると思います`

私は基本的に新しい言語でも`TDD`かつ`クリーンアーキテクチャ`でTODOを作るようにするのですが、その際にどうやってファイルを分割していくのか、DIをするのかなどを知るために他の人のリポジトリをまるまる参考にしています

これは社内のコードが大きな資産となっているのも大きいですが、このスピード感を知ってしまうと仮に社内にコードがなくても、知らない誰かのリポジトリを参考にして実装します

この方法のいいところは、どのファイルにどんな機能を書くのかを迷わずに進めることができます。またテストファイルもほぼほぼ同じような感じでかける印象です。

`TODOアプリ`は大体の言語でリポジトリが存在していると思うので参考にもしやすいです

# 色々な言語を学んでみて

ある程度学習を進めたところで、新しく別の言語始めてもかなりスムーズに学べるようになりました
あの言語と似ている、テストはどのライブラリと似ているなど書きながら思うようになりました

色々な言語をやったことで言語同士の比較ができより技術選択もうまく行くようになるのではないかと思いました

そして何より、学習方法が自分なりに固まって技術を学ぶということのハードルが下がったのがよかったです

私もクリーンアーキテクチャで色々な言語を使ったテスト込みのリポジトリを用意していますので学びたい言語のリポジトリを参考にTODOアプリを作ってみてはどうでしょうか？

https://github.com/jinwatanabe

# おわりに

文字ばかりですごく読みづらいなと思いましたが、読んでいただきありがとうございます。
言いたいことがなんとなく伝わればすごく嬉しいなと思います。

今期の目標は「気づきを与える記事を書く」です。
ぜひともQiitaをフォローいただけたら励みになります

気になることがある方はぜひコメントいただければと思います

# 参考

https://github.com/jinwatanabe
Dockerですべてを削除する

[株式会社TECH LUCK](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)という会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。
- プロジェクトでRailsエンジニアが足りなくて困っている
- Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
- オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご連絡いただけますと幸いです。

# 前提
Macのターミナルでfishを使っている場合に、Dockerの中のすべてのデータを削除したいときがたまにあるのですが、その時に都度調べているので備忘録として残しておきます。

# コマンド
本当にDockerに関連するすべてのデータなのかは不明ですが、思い当たるものはすべて削除しているかと思います。

```bash:ターミナル
docker stop (docker ps -q)
docker rm -f (docker ps -aq)
docker rmi -f (docker images -q)
docker volume rm $(docker volume ls -qf dangling=true)
docker builder prune
docker network prune
```

# 参考文献（圧倒的感謝）
https://qiita.com/hppRC/items/b7e6b93f80ccbf259a8a

https://aduce.jp/docker/remove-docker-build-cache

https://amateur-engineer.com/docker-prune/
なぜ人々がPythonを直接実行する代わりにLangChainのPythonエージェントを好むのでしょうか？

LangChainのPythonエージェントを直接のPython実行に対して選ぶ人々がいくつかの主な理由があるかもしれません：

1.便利さ - Pythonエージェントは、スクリプトやファイルの設定などをせずに、Pythonコードを対話的な形式で実行し、結果を得る簡単な方法を提供します。LangChainがコードの実行を裏で処理します。
例えば、Pythonで100に最も近い素数を見つけるコードは次のようになります。
```
from sympy import sieve, prime

def closestprime(n):       
    if n <= 2: return 2    
    p, q = (prime(j) for j in sieve.search(n))    
    return p if n*n <= p*q else q  

closestprime(100)
```
一方、ユーザーはLangChainのPythonエージェントを使えば、Pythonコードを容易に実行できます。
```
# Load env files 
load_dotenv() 
openai_api_key = os.environ_get('openai_api_key') 

# Create a Python agent 
agent_executor = create_python_agent( 
    llm=ChatOpenAI(openai_api_key=openai_api_key, 
                   temperature=0, 
                   max_tokens=1000, 
                   model_name="gpt-3.5-turbo"), 
    tool=PythonREPLTool(), 
    verbose=True) 

# Run the agent 
agent_executor.run("What is the closest prime number to 100?")
```

2.サンドボックス - LangChainのPythonエージェントは、コードをサンドボックス環境で実行するため、悪意のあるアクセスや意図しないシステムへのアクセスを防ぎます。これにより、自分自身のマシン上でPythonを直接実行するよりも安全性とセキュリティが向上します。
例えば、ユーザーがLangChain上でpython delete_system_files()をテストすると、ファイルの削除は実際には行われず、失敗するか何もしないようになります。

3.リソース - LangChainはPythonコードを実行するための計算リソースを提供します。ユーザーは自分自身のPython環境や依存関係（例：numpy）などを設定する必要がありません。LangChainが環境の設定とコードの実行を処理します。

4.永続性 - Pythonエージェントを使用すると、ユーザーはデータを持続させ、実行間で変数を再利用できます。これにより、独立したPythonスクリプトのように毎回すべてを再定義する代わりに、会話の中でより複雑なロジックを構築することが可能です。
例えば、ユーザーは python x = 1 として変数 x を定義し、後で python print(x) として変数 x を再利用できます。

5.協力 - 複数の人々がエージェントを使用し、お互いの作業に基づいてコードを構築できます。コードは個々のマシンではなく、LangChainのサーバーに永続化されます。
例えば、2人のユーザーはLangChain上のmath_helpers.pyファイルに関数を交互に追加して、コードを共有できます。

6.アクセシビリティ - Pythonエージェントは、ローカルにPythonをインストールしていない、または自分自身のプログラム環境を設定するアクセスがない人々に、Pythonコードを実行する手段を提供します。例えば、LangChainを介してスマートフォンでPythonコードを記述する場合でも、Pythonをインストールする必要がありません。

以上のように、Pythonエージェントは自分自身のプログラミング環境を設定せずに、Pythonを簡単で安全な方法で利用し、持続的な共同作業が可能となります。そのトレードオフとして、ローカルリソースやシステムへの完全なアクセス権があるのではなく、LangChainのホステッドサンドボックス内で実行されます。
Jestでwindow.locationをモックしたい

# はじめに

Jestでテストを書いているときに地味に解決まで時間がかかってしまった箇所があったのでまとめます
案外ネットに記事が見当たらなかったり、ChatGPTも答えを教えてくれなかったりで困りました

# 問題

Jestで`window.location.href`をモックしたいと考えました
しかし、型エラーが発生して困りました

```
'delete' 演算子のオペランドはオプションである必要があります。
```

```
TypeError: Cannot set properties of undefined (setting 'href')Jest
var location: Location
```

```
TypeError: Cannot set properties of undefined (setting 'href')Jest
var location: Location
```

```
window not defined
```

など色々エラーが出て困りました

# 解決方法

まずは`window`を使うために以下のライブラリを入れました

```
$ npm i jest-environment-jsdom
```

そしてテスト環境で利用するように設定します

```json:package.json
  "jest": {
    "testPathIgnorePatterns": [
      "<rootDir>/.types"
    ],
    "transform": {
      "^.+\\.(t|j)sx?$": "@swc/jest"
    },
    "testEnvironment": "jest-environment-jsdom" // 追加
  }
```

その後、以下のように`spy.On`を使ってモックすることでうまく行きました

```ts:test.spec.ts
describe("toNewsHeadlineUnitList", () => {

  let locationReplaceSpy: jest.SpyInstance;

  beforeAll(() => {
    locationReplaceSpy = jest.spyOn(window, 'location', 'get')
      .mockReturnValue({ href: '' } as any);
  });

  it("convert", () => {
    window.location.href = 'http://yourdamain.com';
    expect(window.location.href).toBe('http://yourdomain.com');
  });

  afterAll(() => {
    locationReplaceSpy.mockRestore();
  });
});
```

# 追記

beforeAllよりbeforeEachのほうが良いと思いました。


# おわりに

案外SpyOnを利用する機会があるなぁと感じました
あとChatGPTも同じ解答を繰り返すということが多く、質問するの難しいなとなっています
Windowsのコマンドプロンプト（bat）でOSのバージョン情報取得

# やり方

```bat:
ver
```

結果は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ffdbc2d7-b188-5e35-bcd4-ab8307195ca0.png)

# やり方（エディション）

```bat:
wmic os get caption
```

結果は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/977f8fe6-0f9b-7085-c1c8-8996f8f2a54a.png)

# 蛇足

ユーザー辞書に下記を登録しておくと…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/309b6f14-b0d5-7b78-2225-95d3ab05be76.png)

『ば』と入力して変換するだけで…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1a977ec5-3bba-356e-565d-3d982ec65b50.png)

コマンドが入って、サクッとOSバージョンをクリップボードに入れられる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f024d6b5-2efa-b038-f5b1-d37618e909b1.png)

かなりの頻度で使うコマンドはこんなふうに単語登録すると便利。

# 参考サイトさん

https://maku77.github.io/windows/admin/os-version.html

# バージョン

Microsoft Windows [Version 10.0.19045.3208]
animation.FuncAnimationでmp4動画の作成がうまくいかなかった際の対処法

### 問題
PCを新しくしたので、ImageMagickの最新版を入れて、matplotlib.animation.FuncAnimationでグラフを動かそうとしたら問題が起きましあ。
以下のように、毎回のフレームで画像サイズが変わってしまいます。この点を解決したいです。
gifで作成すると以下のように正常に出力されます。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/e247e46e-cdaa-f586-5734-05cfac11427b.gif)

しかし、mp4で作成すると最初の1枚目は通常に出力されますが、２枚目からは拡大された画像が出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/b684e9f7-1888-5a59-32d6-4679ec2e9764.png)
*mp4の１枚目の画像*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/17edb434-4503-7fc0-72d5-f43501ecbae7.png)
*mp4の２枚目の画像*

### 環境
windows 11
imagemagick7.1.1
matplotlib 3.7.2

### ソースコード
上のサンプルコードは https://qiita.com/yubais/items/c95ba9ff1b23dd33fde2 からいただきました。
```py
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()

def plot(data):
    plt.cla()                      # 現在描写されているグラフを消去
    rand = np.random.randn(100)    # 100個の乱数を生成
    plt.plot(rand)            # グラフを生成
    plt.xlabel('x')

ani = animation.FuncAnimation(fig, plot, interval=100, frames=10)
ani.save("output.gif", writer="imagemagick", dpi=100)
```

### 解決法
matplotlibrcのANIMATIONのセクションのanimation.writer:  ffmpegを有効にしたら解決しました。
つまり、imagemagickが悪さしていたようです。
Windowsのbatでユーザーの入力値を元に処理

# やり方

```bat:入力値を元にファイルやフォルダーを検索するサンプル
rem このbatと同じフォルダーに存在している、ファイルやフォルダーの部分一致検索。
rem 検索文字列はユーザーからの入力値。

rem ユーザーからの入力値を保持する変数。
set input_from_user_=

rem ユーザーに入力してもらう。
set /p input_from_user_="検索する単語を入力して下さい。"

rem 検索。
dir *%input_from_user_%*

rem 検索結果が確認できるように、コマンドプロンプト画面を閉じずに残す。
pause
```

bat起動すると下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/054a2884-c228-f47a-5dbf-c5431587b327.png)

フォルダーの構成が下記の場合…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3c97e8e1-1452-03e0-b74d-4342d619db79.png)

『あああ』と入力すると、その値を使って処理が行われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4327451d-c50b-8345-c57c-271d9464bb8a.png)

なんでもいいのでキー入力するとコマンドプロンプト画面は閉じる。

# 参考サイトさん

https://jj-blues.com/cms/command-set/

# バージョン

Windows 10 Pro 22H2 19045.3208
Kaskada Kubernetesインストール

# はじめに

先日、以下の記事を発表しました。

https://qiita.com/yoshiyuki_kono/items/7dc7bdad5e02ff986f5d

公式ドキュメントの学習過程の記録として、以下の記事をまとめてみました。

本稿情報のソースとして、下記ドキュメントを参照ください。

https://kaskada.io/docs-site/kaskada/main/installing/kubernetes.html#url:https://helm.sh/docs/intro/install/

Helmチャートを使用すると、Kubernetes クラスター内で Kaskada を構成、インストール、アップグレードできます。


## 前提条件
 - Helm 3 以上
 - 実行中の Kubernetes クラスター

## カスカダ-カナリアヘルムチャート
ここで紹介する、Kaskada Canary Helm Chart は、可能な限り単純な構成で kaskadaサービスをデータの外部ストアへの永続化設定とともに、インストールします。

https://github.com/kaskada-ai/helm-charts/tree/main/charts/kaskada-canary

この設定では、kaskada サービスは 1 つのポッド内の 2 つのコンテナとして実行され、データベースを接続されたストレージ上のファイルとして永続化します。データをローカルに保存することもできますが、理想的にはオブジェクトストアにアクセスできる必要があります。

このチャートは主に初期テストを目的としており、本番運用では使用しないでください。

### Kaskada Canary Helm チャートをインストールする
Kaskada の Helm リポジトリをローカル Helm インストールに追加します。

```
helm repo add kaskada https://kaskada.io/helm-charts
```
チャート リポジトリを更新します。

```
helm repo update
```

必要に応じて、`values.yaml`ファイルの設定を編集することができます。たとえば、次の構成は、s3認証メカニズムとして AWS アクセス キー/シークレットを使用するオブジェクト ストアとして構成し、イングレス用のサービスにロード バランサーを追加します。

```yaml
auth:
  aws:
    accessKeyId: <your_access_key_id>
    secretAccessKey: <your_secret_access_key>
    region: <s3_bucket_region>

storage:
  objectStore:
    bucket: <s3_bucket_name>
    type: s3
  dbData:
    storageClassName: gp2
  tmpData:
    storageClassName: gp2

service:
  type: LoadBalancer
```


チャートをデプロイします。

定義された構成を使用してデプロイします。

```
helm install kaskada-canary kaskada/kaskada-canary -f values.yaml
```