OmniAICreator/Qiita-1.07M huggingface dataset:
ASP.NET Coreをやってきた人がReactを少し触って感じたこと

## 初めに

初めてReactでアプリを作成したので、自分が使ってきたASP.NET Coreと比べて感じたことを書きます。

## 結論

cshtmlでページ読み込み時に行なっていたhtmlの作成が、手軽に行えるようになった感じの印象。

そのため、cshtmlのコードを書いた経験のある人なら、_Partialなどの経験も含めて、だいぶ学習しやすいように感じた。

また、役割が被りがちな関係上、ASP.NETとReactが相性悪いと言われる理由がわかった。

現状でレガシーなASP.NETを業務で使っていて、キャリアアップしたい人にとっては、Blazorなどの最新のASP.NET関係の技術を学ぶよりも、フロントエンドでシェアが大きいReactの方を学んでいくのがいいのかもしれない。
※ASP.NETはバック・フロントの両方の機能があるので、あまり単純比較はできない

## 終わりに

全然別カテゴリに見える技術でも、中身を見れば意外と既存の経験が活かせたりするので、さわりだけでもいろいろ知っておくのがいいと思いました。〆

## JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp
WinActorの画像マッチング新機能「フォルダ指定」を使ってみた

「RPA Advent Calendar 2024」8日のEMIです。
年末気分が高まりますね。

WinActor7.5では画像マッチングノードが刷新されました。

新しく追加された、「実行時にマッチング画像を取得」⇒「フォルダ指定」を使ってみたので紹介します。
今までは1個のファイルしか指定出来ませんでしたが、フォルダ指定が出来るようになったことで、マッチング画像の複数のファイルをフォルダに格納し、フォルダ内のいづれかの画像にマッチすればアクションしてくれるようになりました！

これを使うと解像度の違うPCでそれぞれシナリオを実行しても、それぞれのPC用のマッチング画像をあらかじめフォルダに格納することで、どのPCでもアクションしてくれるノードとなるというわけです:star2:

今回は2個のPCを使うことが出来なかったため、1個のPCでディスプレイの解像度を「1600×900」と「1920×1080」と変更してそれぞれ実行してみることとしました。

## フォルダ指定の設定手順

### 設定手順１（キャプチャを取得）

予め、操作対象のウィンドウの操作したい箇所のキャプチャを取得し、フォルダに格納しておきます。
今回は「PDFをChromeで開いたときのこのダウンロードボタンをクリックする」というアクションを画像マッチングで実装したいと思います。
実際のシナリオ作成で、これがUIオートメーション等で押せなくて、画像マッチングを使ったのです:sweat:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/4f40604b-c9d6-9566-fbab-e16e68a00a39.png)


ディスプレイの解像度を「1600×900」と「1920×1080」と変更してそれぞれのダウンロードボタンのキャプチャを取得し、2個の画像ファイルをフォルダに格納しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/0c06c22b-c310-a37e-590d-cd53adf32d1e.png)


### 設定手順２（基本設定のプロパティ設定）

では画像マッチングノードのプロパティ設定をします。
基本設定タブの「ウィンドウ識別名」を設定して、「アクション」を左ボタンクリックに変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/401019de-9f0c-06fe-6833-4efb230db5b5.png)

### 設定手順３（詳細設定タブのプロパティ設定）

次に詳細設定タブで「実行時にマッチング画像を取得」にチェックを入れ、フォルダを選択し、「マッチング画像パス」にはさきほどの画像ファイルを格納したフォルダを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/391df927-ba9f-884a-e2dd-fc15333f20ce.png)


設定は以上です！

## 実行結果
ディスプレイの解像度を「1600×900」にしてシナリオを実行しても、「1920×1080」にして実行しても、両方とも無事、ダウンロードボタンを押すことが出来ました:hugging:

画像マッチングは解像度の異なるPC上ではマッチせずに上手くいかないため、それぞれのシナリオを準備する必要がありました。
また、画像が変更になった時もシナリオを修正する必要があるからメンテナンス性が良くないなど、あまり良い印象が無いと思います。
この機能を使うことで、画像変更時もシナリオを修正することなく画像ファイルの取得のみとなりメンテナンスの手間を最小限に抑えることが出来るのではないでしょうか？

これからも積極的に使っていきたいと思います！
【Visual Studio Code】Vscodeの拡張機能を作ってみた

# はじめに
身近なところにVscodeの拡張機能がたくさんあったので、
自分でも作ってみようと思いました。
# 作り方
まず拡張機能の雛形を使います
```bash
$ npm install -g yo generator-code
$ yo code

? What's the name of your extension? 
# 拡張機能の表示名
? What's the identifier of your extension?
# 拡張機能のID
? What's the name of your extension?
# 拡張機能の説明
? Initialize a git repository? (Y/n)
# Gitのリポジトリを初期化するかどうか
```
src/extention.tsをこんな感じにしました
```typescript:extention.ts
import { randomInt } from 'crypto';
import * as vscode from 'vscode';

function convertHandNameToInt(hand:string){
	if (hand === "グー"){
		return 0;
	}else if (hand === "チョキ"){
		return 1;
	}else if (hand === "パー"){
		return 2;
	}else{
		return null;
	}
}

function convertIntToHandName(hand:number){
	if (hand === 0){
		return "グー";
	}else if (hand === 1){
		return "チョキ";
	}else if (hand === 2){
		return "パー";
	}
}

function win(ennemy_hand:number){
	vscode.window.showInformationMessage(`勝ち！相手の手は ${convertIntToHandName(ennemy_hand)} でした！`);
}

function draw(ennemy_hand:number){
	vscode.window.showInformationMessage(`あいこ！相手の手は ${convertIntToHandName(ennemy_hand)} でした！`);
}

function lose(ennemy_hand:number){
	vscode.window.showInformationMessage(`負け！相手の手は ${convertIntToHandName(ennemy_hand)} でした！`);
}

/* 
	グー: 0
	チョキ:1
	パー:2
*/

export function activate(context: vscode.ExtensionContext) {
	let statusBarButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
	statusBarButton.text = '✊ジャンケン';
	statusBarButton.command = 'jankencode.doJanken';
	statusBarButton.show();

	const disposable = vscode.commands.registerCommand('jankencode.doJanken', () => {
		let ennemy_hand = randomInt(3);
		vscode.window.showQuickPick(["グー","チョキ","パー"])
		.then(selectedCommand => {
			if (selectedCommand){
				let my_hand = convertHandNameToInt(selectedCommand);
				if (my_hand === ennemy_hand){
					draw(ennemy_hand);
				}else{
					if (my_hand === 0){
						if (ennemy_hand === 1){
							win(ennemy_hand);
						}else{
							lose(ennemy_hand);
						}
					}else if (my_hand === 1){
						if (ennemy_hand === 0){
							lose(ennemy_hand);
						}else{
							win(ennemy_hand);
						}
					}else if (my_hand === 2){
						if (ennemy_hand === 0){
							win(ennemy_hand);
						}else{
							lose(ennemy_hand);
						}
					}
				}
			};
		});
	});

	context.subscriptions.push(statusBarButton);
	context.subscriptions.push(disposable);
}

export function deactivate() {}
```

じゃんけんのコードです。

# おわりに
また他のものも作ってみようと思います。
Web MIDI APIは将来Web Workerから利用可能になりそうです！

なんか、空いてるようなので小ネタで乱入します！

### 誰だお前?

趣味で音の鳴るアプリとか作って遊んでる人です。
[最近作ってるアプリ。生成AIで作った画像からサウンドコラージュを無限に生成します](https://capp.mz4u.net/rg/)

### Web MIDI API が Web Worker で動作するように！

最近、[Web MIDI API](https://www.w3.org/TR/webmidi/) の仕様（Working Draft）がなんと9年ぶり！に更新されました。

すっごい気になる！内容が含まれていますので紹介します。

- `MIDIAccess` へ [Transferable](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) 属性追加！

![MIDIAccess.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31758/17b3e0e4-e338-2cbd-07a7-9e2c860e49d8.png)

![transfarable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31758/430eeb07-3dff-e43d-a05c-6d34fba8d89f.png)
引用元：https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects


- `MIDIAccess`や `MIDIInputMap` `MIDIOutputMap` などのオブジェクトの動作コンテキストに `Worker` 追加

これ、どういう意味かというと、今までWindowコンテキスト（メインスレッド）でしか動作しなかった Web MIDI APIが Workerで動作するようになる、ということですね！

`WorkerNavigator`に`requestMIDIAccess()`を生やす、という修正ではないので、あくまで Windowコンテキストでユーザーパーミッションを解決してから `postMessage` で Web Worker に `MIDIAccess` を転送し、そこで使ってもらう。という使い方になるようです。

実装が超楽しみですね！

### まだブラウザには実装されてないので動きません。

仕様追加されてるけどChromeにまだ実装されてないよ！
という issue があげられています。

https://issues.chromium.org/issues/379805727

気になる方はチェックするようにしましょう！

最終コメントが

> mj...@chromium.org<mj...@chromium.org> #4Nov 22, 2024 03:43AM
> 
> Sorry for the delay, yes we haven't implemented this yet and we should. I will set to Available.

とのことで、めちゃくちゃ期待できますね！

### おまけ。確認用コード！

実装されたら即確かめられるように、`MIDIAccess` を Web Workerに転送するだけのコードを作りました！

```index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<title>MIDIAccess worker transfer test</title>
<style>
</style>
</head>
<body>
<script type="module">
const access = await navigator.requestMIDIAccess();
if(access == null){
  console.log("MIDI not supported.");
}else{
  console.log("MIDI supported.");
  const wk = new Worker("./worker.mjs",{type:"module"});
  wk.postMessage(access,[access]);
  console.log("MIDIAccess transfered.");
}
</script>  
</body>
</html>
```

```worker.mjs .js
self.onmessage = (msg) ={
  let midiAccess = msg.data;
  console.log("midiAccess received");
};
```

現在は、まだ `MIDIAccess`を転送できないぞ！というエラーが出てWorkerに `MIDIAccess`を届けることができません。

### まとめ

- まだ実装されてないけど Web MIDI API が web worker で動くようになりそうです。
- 宣伝：[KTECのアドカレ](https://qiita.com/advent-calendar/2024/kddi-technology) も見てね！
Workato：文字コード（エンコーディング）が壊れたファイルをWorkatoで扱うには

# はじめに

Workatoでは、文字コード（エンコーディング）を自動的に判別して適切な結果で出力される、あるいはformulaモードに切り替えて`as_string`メソッドを利用し適切な文字コードを選択することにより適切な結果で出力されます。

しかし、何らかの理由で文字コードが壊れているファイルの場合、文字化けしてしまう場合があります。また、formulaモードに切り替えて`as_string`メソッドで正しい文字コードを指定しても文字化けしてしまう場合があります。

このような場合は、次に示す手順のようにPythonコネクタを利用して文字コードを指定し、デコードすることで、文字化けせずに結果を出力することが可能です。

# 手順

Boxからテキストファイルをダウンロードし、指定された文字コードでデコードするレシピを例として説明を進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/fb9fa3ad-c81a-f7a3-2336-16a3ec401fb0.png)

Step3にPythonコネクタを追加し、次のように設定を進めます。

## Input fields

`value` と `encoding` の2つの文字列型のフィールドをセットします。

`value`にはBoxの`File contents`をセットします。なお、`File contents`はInputStream型でありそのまま扱うことが出来ないため、文字列型へキャストを行います（`.to_s`メソッドを追加します）。また、現状をそのままコードに渡せるようBase64エンコードを行います（`.encode_base64`メソッドを追加します）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/f0087e5a-e2fc-d8b6-2e53-41b2c24a4784.png)

## Output fields

`value` という文字列型のフィールドをセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/35b6debc-2689-a6fe-5817-719d4d8a6b26.png)

## Code

次のコードを入力します。

```python
import base64

def main(input):
    value =  base64.b64decode(input['value']).decode(input['encoding'], 'strict')

    return {
        'value': value
    }

```

# 結果の確認

このレシピを実行すると、3ステップ目でデコード後の結果を確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d5d72b28-b418-edd4-56b3-fe5a657005e9.png)
CDKでSSOのRoleをEKSのmastersRoleに登録する方法

# 概要

Identity Centerで作成したSSO用Roleの認証情報を利用して、kubectlコマンドを叩きたい場合、K8sのRBACに登録する（認可）必要があります。

通常はCLIやコンソールを利用すれば作成したユーザーがmastersRoleとして登録されるますがCDKの場合勝手が違って大変だったので記事にします。

# 解決策

SSO用RoleのARNを一部改変する必要があります。

```tsx
arn:aws:iam::XXXXXXXXXXXX:role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX
↓
arn:aws:iam::XXXXXXXXXXXX:role/AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX

```

改変したARNでmastersRoleを設定することで起動時にSSO用RoleがRBACに登録されます。

```tsx
const eksCluster = new eks.FargateCluster(this, 'EksCluster', {
    version: eks.KubernetesVersion.V1_31, // EKSのバージョン
    kubectlLayer: new KubectlV30Layer(this, 'KubectlLayer'),
    vpc: vpcForEks,
    albController: {
        version: eks.AlbControllerVersion.V2_8_2, // ALB Ingress Controllerのバージョン,
    },
    mastersRole: iam.Role.fromRoleArn(this, 'EksMasterRole', 'arn:aws:iam::XXXXXXXXXXXX:role//AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX'),
});
```

# EKSのRBACとIAMの繋がり

![https://dev.classmethod.jp/articles/eks-cluster-access-control/　より](https://devio2023-media.developers.io/wp-content/uploads/2020/05/eks-cluster-auth-01-640x440.png)

この図のようにIAMで認証し、k8sのRBACで認可を行っています。

IAMでadmin権限を持っていてもEKSのk8sから取ってみれば一般ユーザーでしかないので、k8s側で権限を付与する必要があります。

# 問題点1：CDKのデプロイによる問題

CDKでEKSをデプロイした場合、KubectlLayerを持つLambdaが自動生成されLambda経由でEKSを構築します。

[公式のドキュメント](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-eks-readme.html#architectural-overview)
[解説した記事](https://qiita.com/watany/items/daf433338de5b6858ed6)

そのため、EKSクラスター構築後はCLIやコンソールで操作したユーザが`system:masters`の権限を持っていますが、CDKで作成する場合は`cdk deploy`を実行するユーザーではなく、自動生成されたLambdaがこの権限を持ちます。

そこでCDKは明示的にmastersRoleを設定する必要があります。

```tsx
const eksCluster = new eks.FargateCluster(this, 'EksCluster', {
    version: eks.KubernetesVersion.V1_31, // EKSのバージョン
    kubectlLayer: new KubectlV30Layer(this, 'KubectlLayer'),
    mastersRole: iam.Role.fromRoleArn(this, 'EksMasterRole', 'arn:aws:iam::XXXXXXXXXXXX:role//AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX'),
});
```

# 問題点2：SSOのRoleのARN問題

SSO用RoleのARNをコンソール上で確認すると、通常のIAM RoleのARNとは異なるpathがあり、このpathのせいでエラーを引き起こす要因になっていました。

```tsx
arn:aws:iam::XXXXXXXXXXXX:role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX
```

[公式のQA](https://repost.aws/ja/knowledge-center/eks-configure-sso-user)によると、

```tsx
aws-reserved/sso.amazonaws.com/ap-northeast-1
```

このpathが良くないらしく、EKSが理解できるARNに変更する必要があるみたいです。

```tsx
arn:aws:iam::XXXXXXXXXXXX:role/AWSReservedSSO_EKSAdmin_XXXXXXXXXXXXXXXXXX
```

# 引用
https://dev.classmethod.jp/articles/eks-cluster-access-control
https://docs.aws.amazon.com/cdk/api/v1/docs/aws-eks-readme.html#architectural-overview
https://qiita.com/watany/items/daf433338de5b6858ed6
フルリモートのあるある課題とその解決方法

この記事は [クラウドワークス グループ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ2の12日目の記事です。

こんにちは。
crowdworks.jpでエンジニアをしている @tetsu333 です。
クラウドワークスには2024年4月に中途入社し、現在フルリモート歴8ヶ月目になります。
今回は、フルリモート勤務を通して私が感じた課題と、それに対する解決方法についてご紹介します。

# まずはフルリモートの良さについて
実際にフルリモートで働いてみて感じたのは、そのメリットの大きさです。
私自身、この働き方をとても気に入っており、これからも続けたいと思っています。
まずは、私が感じたフルリモートの良さをご紹介します。

## 通勤しなくていい
天候や体調次第で、通勤が辛いと感じたことはありませんか？
フルリモートなら、そのような通勤の負担から解放されます。
私自身、汗かきなので、特に真夏の通勤が不要になったことは大きなメリットだと感じています。

## ワークライフバランスを実現しやすい
フルリモートでは通勤時間がなくなる分、1日の自由時間が増えます。
私の場合、朝は余裕を持って子どもを保育園に送り届けることができ、夜は毎日「おやすみ」と声をかけてあげることが出来ています。
子供を持つ親にとっては嬉しい働き方だと感じています。

## 作業に集中できる
出社していると、周りの状況に目を配ったり、つい気を遣ったりしてしまうことはありませんか？
フルリモートでは、物理的に一人の環境で働けるため、周囲を気にせず集中しやすいと感じています。

# 良いことだけではない
フルリモートには多くの良さを感じていますが、実際に働いてみるといくつか課題を感じる場面もあります。
ここからは、本記事のテーマでもある「課題」と、その「解決方法」について、私の経験をもとに3つご紹介していきます。

# 課題①: 自制心が求められる
リモートワークでは、オフィスのように周囲の目がないため、仕事とプライベートの切り替えが曖昧になりがちです。
その結果、気が散る要素に流されやすく、自制心が求められると感じます。

## 解決方法: 仕事が捗る環境作り
集中力を高め、効率よく仕事を進めるためには、自宅でも仕事に適した環境を整えることが大切です。
自制心に頼るだけでは限界があるため、環境を整えることで自然と集中しやすくする工夫が効果的です。
ここでは、その具体的なポイントをご紹介します。

### 気が散るものを片付ける
特に、机の上を整理整頓することで、集中力を保ちやすくなると感じています。
私はスマホを引き出しにしまい、つい触ってしまわないようにもしています。

### 姿勢を整えるアイテムを使う
ノートパソコンだけでは姿勢が悪くなり、集中力も低下しがちです。
私は、PCスタンドで画面の高さを目線に合わせ、外付けキーボードで手首に負担をかけない配置に変えたことで、姿勢が大きく改善され、作業が快適になりました。
これらのアイテムは比較的手軽に導入できるため、リモートワークをより快適にするためのおすすめアイテムです。

### 快適な椅子を選ぶ
1日の大半を過ごす椅子選びは非常に重要です。
私は、少しお金をかけて快適さを重視した椅子を選びました。
身体への負担を軽減してくれる設計で、長時間の作業でも疲れにくく、快適に過ごせています。

# 課題②: 運動不足になる
通勤がなくなることで、単純に1日の運動量が減りがちです。
日によっては、家から一歩も出ないということもありえます。

## 解決方法: 仕事前に運動する
運動不足を解消するためには、やはり日々の生活の中で運動を取り入れることが大切です。
私の場合、仕事の前に運動することで、1日のスタートを良い形で切れるようになりました。
以下にその理由をご紹介します。

### ドーパミンを分泌して集中力向上
運動をすると脳内でドーパミンが分泌され、集中力やモチベーションが高まると言われています。
私は軽いストレッチや筋トレを取り入れることで、朝から頭が冴えた状態で仕事に取り組めるようにしています。

### 朝散歩はセロトニンが活性化してメンタルに良い
朝の散歩はセロトニンを活性化し、メンタルの安定に役立つと言われています。
私の場合は、子どもを保育園に送るための移動やジムに向かう道のりが、ちょうど良い散歩になっています。

### 心身ともに健康的に
運動不足の解消だけでなく、メンタルの改善にもつながり、仕事への良い影響も感じています。
まさに「一石二鳥」の取り組みとして、気負わず続けることを大切にしています。

# 課題③: コミュニケーションスタイルの変化
リモートワークでは、出社して働くスタイルとは異なるコミュニケーション方法が求められます。
人と直接会う機会が減ることで、情報を共有するスムーズさや、信頼関係を築くプロセスに新しい工夫が必要です。

## 解決方法: リモート環境での効果的なコミュニケーション
リモートワークならではのコミュニケーションスタイルに適応するためには、新しい方法を取り入れる意識が欠かせません。
ここでは、私自身が取り組んでいる工夫をご紹介します。

### 言語化力を高める努力
リモートワークでは、チャットやWeb会議システムが主なコミュニケーション手段となるため、言語化力の重要性を感じています。
チャットでは短い文章で意図を的確に伝えるスキルが求められ、ビデオ会議では非言語情報が不足する中で分かりやすく話す工夫が欠かせません。
私自身、まだ勉強中ですが、こうしたスキルを少しずつ磨いていきたいと思っています。

### 気軽な雑談の仕組みを作る
雑談は良好な人間関係を築く上で重要だと言われていますが、話題に困ることもあります。
私の所属チームでは、「雑談のテーマを提案してくれるツール」を活用し、日常的な話題を共有しやすくしています。
こうした仕組みがあると、気軽に会話を始めやすくなり、オンラインでも自然なコミュニケーションが生まれます。

### 飲み会は距離を縮める貴重なチャンス
最近開催された飲み会では、普段あまり関わりのないメンバーと自然に交流できるきっかけになりました。
私は特別お酒が好きなわけではありませんが、リモートワークだからこそ、直接会う機会の重要性を再認識しました。
たまに開催される飲み会やオフラインのイベントは、リモートでは築きづらい信頼関係を補う貴重な場だと感じます。

# 最後に
フルリモートで快適に働くためには、自分に合ったセルフマネジメントが欠かせません。
今回ご紹介した課題と解決方法が、少しでも皆さんの参考になれば嬉しいです。

最後までお読みいただき、ありがとうございました！
React 19のuseActionStateを使ったForm開発

#### 参考記事
:::note
[[Zenn] React 19によって状態管理はどのように変わるのか](https://zenn.dev/aishift/articles/051d5d3fd1f8a6)
:::
:::note
[[Zenn] React 19の新機能まるわかり
](https://zenn.dev/uhyo/books/react-19-new)
:::

### 1. `useActionState` の基本

`useActionState`は、React19の新しいフックで、アクションの状態を管理するために使われます。このフックは、状態の変更をトリガーし、コンポーネントの再レンダリングを引き起こすことができます。

#### 使用例
```react
import { useActionState } from 'react';

function MyForm() {
  const [formState, setFormState] = useActionState({ name: '', email: '' });

  const handleChange = (e) => {
    setFormState({ ...formState, [e.target.name]: e.target.value });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formState);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" value={formState.name} onChange={handleChange} />
      <input type="email" name="email" value={formState.email} onChange={handleChange} />
      <button type="submit">送信</button>
    </form>
  );
}
```

### 2. React Hook Form の基本

React Hook Formは、フォームの状態管理を簡素化するためのライブラリです。バリデーションやエラーハンドリングが容易で、パフォーマンスも良好です。

#### 使用例
```react
import { useForm } from 'react-hook-form';

function MyForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name', { required: true })} />
      {errors.name && <span>名前は必須です</span>}
      
      <input {...register('email', { required: true })} />
      {errors.email && <span>メールは必須です</span>}
      
      <button type="submit">送信</button>
    </form>
  );
}
```

### 3. 比較

#### 状態管理
- **useActionState**: 状態はローカルで管理され、シンプルなフォームには適していますが、バリデーションや複雑なロジックを必要とする場合は手動で実装する必要があります。
- **React Hook Form**: フォームの状態やバリデーションが組み込まれており、特に大規模なフォームや複雑なバリデーションが必要な場合に強力です。

#### バリデーション
- **useActionState**: バリデーションを自分で実装する必要があります。エラーメッセージの管理も手動で行います。
- **React Hook Form**: バリデーションのためのオプションが豊富で、簡単にエラーメッセージを表示できます。フォームの状態も自動で管理されます。

#### パフォーマンス
- **useActionState**: 小規模なフォームでは十分なパフォーマンスを発揮しますが、状態変更が多い場合は再レンダリングが多くなる可能性があります。
- **React Hook Form**: 最小限の再レンダリングを実現しており、大規模なフォームでもパフォーマンスが良好です。
C言語組み込みzipライブラリminizの最近の使い方メモ

古い記事とか読んでそのままやっても駄目だったんでその結果をメモ。
例ではアーカイブ中のファイルをソートしてファイル名とファイルインデックスを返し、
オンメモリ上に解凍するかんじ。

下記からライブラリをダウンロード。
https://github.com/richgel999/miniz/releases

```
#define MINIZ_HEADER_FILE_ONLY
#include "miniz.h"
#include "miniz_zip.h"

int zip_files(char* path, mz_zip_archive* zip_archive, char*** files, int** indexes) {
  if (access(path, F_OK) == -1) {
    fprintf(stderr,"error file not found\n");
    exit(EXIT_FAILURE);
  }

  memset(zip_archive, 0, sizeof(mz_zip_archive));
  mz_zip_reader_init_file(zip_archive, path, 0);

  int numfiles = mz_zip_reader_get_num_files(zip_archive);

  *files = (char**) malloc((numfiles + 1) * sizeof(char *));
  memset(*files, 0, numfiles + 1);

  *indexes = (int*) malloc((numfiles + 1) * sizeof(int));
  memset(*indexes, 0, (numfiles + 1) * sizeof(int));

  for (int u = 0; u < numfiles; u++) {
    char getfile[516];
    int rr = mz_zip_reader_is_file_a_directory(zip_archive, u);

    if (rr == 1) { // is directory
      continue;
    }

    int r = mz_zip_reader_get_filename(zip_archive, u, getfile, sizeof(getfile));
    int i = get_number(getfile);
    char* file = (char*)malloc((strlen(getfile) + 1) * sizeof(char));
    memset(file, 0, (strlen(getfile) + 1) * sizeof(char));

    strcpy(file, getfile);
    (*files)[i] = file;
    (*indexes)[i] = u;
  }

  return numfiles;
}


int main(int argc, char* argv[]) {
  char* path = argv[1];
  mz_zip_archive zip_archive;
  char** files = 0;
  int* indexes = 0;

  int count = zip_files(path, &zip_archive, &files, &indexes);
  for (int i = 0; i <= count; i++) {
    printf("%03d %03d %s\n", i, indexes[i], (files[i] == 0) ? "" : files[i]);
    size_t size;
    void* file_contents;
    file_contents = mz_zip_reader_extract_to_heap(&zip_archive, indexes[i], &size, 0); 
  }
}
```

ビルド例。
```
cc -Wformat -o ziplist main.c -I miniz-3.0.2/ miniz-3.0.2/*.c
```
【TypeScript】Exclude<T, U>の自作（type-challenges 初級編 43・Exclude）

## お題
`Exclude<T, U>`を使用せず、ユニオン型`T`から`U`で指定したユニオン型を取り除いたユニオン型を返す型`MyExclude`を実装する。

## やりたいこと
```typescript
type result = MyExclude<"a" | "b" | "c", "a">  // "b" | "c"
```

## 解答
```typescript
type MyExclude<T, U> = T extends U ? never : T;
```

## 解説

### 処理の流れ
- `<T, U>`
ユニオン型`T`と、取り除きたい型`U`を引数にとるようにする。
- Conditional Typesによって評価を行う。
  - `U`の場合は、`never`を返す
  - `U`ではない場合は、そのまま`T`の値を返す

### そもそも`Exclude<T,U>`とは...
ユニオン型`T`から`U`で指定した型を取り除いたユニオン型を返すユーティリティ型
```typescript
type Grade = "A" | "B" | "C" | "D" | "E";
type PassGrade = Exclude<Grade, "E">; // "A" | "B" | "C" | "D";
```

### ユニオン型の条件分岐の場合に何が起こる？
Conditional Typesの**Union distribution**と言う性質により、各要素に対して評価が行われる（分配法則）。
```typescript
// MyExclude<"a" | "b" | "c", "a"> の場合

("a" extends "a" ? never : "a") | ("b" extends "a" ? never : "b") | ("c" extends "a" ? never : "c")

-> never | "b" | "c"
-> "b" | "c"
```

### Conditional Typesとは...
https://qiita.com/yuto99999/items/057e28323118c4ac5de0#conditional-types%E5%9E%8B%E3%81%AE%E6%9D%A1%E4%BB%B6%E5%88%86%E5%B2%90%E3%81%A8%E3%81%AF


## 参考記事
### `Exclude<T,U>`
[Exclude<T, U> | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/type-reuse/utility-types/exclude)
### Union distribution
[ユニオン分配 (union distribution) | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/type-reuse/union-distribution)

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/00043-easy-exclude/README.ja.md
【ネットワーク】３分間NetWorking 第26回〜27回 OSI参照モデル レイヤ3 ARP、DNS

# はじめに
この記事は、3分間NetWorkingを読んでインプットした知識をアウトプットするために執筆しています。
学習内容のまとめ、学習してみての所感や疑問などを記載しています。
記事を読んでみて、間違っていることへの指摘や感想などありましたら、ぜひコメントをいただければ幸いです。
3分間NetWorkingのリンクは以下の通り。
https://www5e.biglobe.ne.jp/aji/3min/

#### :bulb:記事のトピックス
・ARP
・DNS

# ARP
前回、データの転送には送信元MACアドレス、送信元IPアドレス、宛先MACアドレス、宛先IPアドレスが必要と話しました。
送信元MACアドレスはNICが取り付けられた時点で付与され、自動的に取得されます。
送信元IPアドレスは、ネットワーク管理者が手動で付与する静的IPアドレス（スタティックIPアドレス）と、DHCPをサーバとクライアントを利用して取得する動的IPアドレス（ダイナミックIPアドレス）がありました。

今回は宛先MACアドレスの取得方法についてまとめます。
宛先MACアドレスを取得するには、ARP（Address Resolution Protocol）というプロトコルを使用します。
ARPは宛先IPアドレスからMACアドレスを調べる仕組みです。宛先IPアドレスを知った後に、そのIPアドレスにMACアドレスが何かを聞いて確認します。

# ARPテーブル
ARPでのMACアドレス取得の流れをまとめます。
まずは、データ転送を希望するホストは、宛先IPアドレスを取得します。
IPアドレス取得後、ARPテーブルと呼ばれる、IPアドレスとMACアドレスの対応表を参照し、該当のIPアドレスのMACアドレスを確認します。
このテーブルに知りたい宛先IPアドレスと宛先MACアドレスの対応が載っていれば、宛先MACアドレスを取得することができますが、対応が載っていない場合もあります。
その場合、ARP要求でテーブルに載せる必要があります。

# ARPリクエスト・ARPリプライ
ARPはレイヤ3のプロトコルですが、IPアドレス解決のためのプロトコルなので、IPパケットを使用しません。ARPパケットという独自のパケットを使用してデータ転送を行います。
IPパケットではレイヤ4などの上位レイヤのデータを引き継いで使いますが、ARPはレイヤ3以降のレイヤでしか使いません。

#### :label:ARPリクエスト・リプライの流れ
1.宛先にデータを転送するために、宛先IPアドレスを取得
2.ARPテーブルを参照し、宛先IPアドレスと宛先MACアドレスの対応を確認
3-1.対応があった場合、そのまま宛先MACアドレスを取得してARPパケットで転送
3-2.対応がなかった場合、ARPリクエストをブロードキャストで各ホストに送る
4.ARPリクエストを受け取った各ホストは、ARPパケットの中の宛先IPアドレスと自分のIPアドレスを比較する
→一致しなければ無視
→一致すれば、ARPリプライを送信
5.ARPリプライを受け取ったホストは、ARPテーブルにそのMACアドレスを追加する
6.4つのアドレスが揃い、データをARPパケットで転送する

# ARPが多発することによる懸念
ARPはブロードキャスト通信のため、全員宛の通信が多発することによりネットワークの帯域幅を多く消費します。
スイッチやブリッジはフィルタリングによって宛先を指定することができるが、ブロードキャストはフィルタリングできないので、トラフィックに影響を及ぼしやすいです。
ブロードキャストが多発して、ネットワーク全体が通信できない状況になることをブロードキャストストームと言います。

# DNS

#### :label:ドメイン名とホスト名

宛先IPアドレスを知る方法です。
送信する相手のコンピュータの名前をドメイン名、ホスト名と言います。
ドメイン名はIPアドレスを人間が見やすいように変換したもので、IPアドレスと同じくコンピュータのネットワークの住所を表しています。
正確にはコンピュータの住所はホスト名の方ですが、ドメイン名の一部になっていることが多いです。
ドメイン名は正確にはネットワーク全体や組織を識別する名前になります。

IPアドレスと同じようにユニークな名前である必要があり、ドメイン名はICANNが管理しています。
ホスト名は組織のネットワーク管理者が付けます。
しかし、人間が見やすい形にしても、データを送信するにはどうしてもIPアドレスとして取得する必要があります。

#### :label:DNS（ドメインネームシステム）
そこで、名前とIPアドレスを対応させるデータベースを持っているDNSサーバーに問い合わせを行い、宛先IPアドレスを取得します。
DNSサーバーは各組織に一つずつ、その組織のドメイン名とホスト名のみを管理しています。
そのため、他の組織のドメイン名やホスト名からIPアドレスを知りたいときは、他の組織のDNSに聞くことになります。

DNSの一連の流れとしては以下の通りです。

1.ユーザーがドメイン名を入力
2.DNSでまずは過去に同じようなリクエストがなかったか、キャッシュを確認する
3-1.キャッシュがあれば、それを返して終了
3-2.キャッシュがなかった場合は、新たにIPアドレスを取得して返す

これらの流れにより、ドメイン名からIPアドレスを取得することができます。

# まとめ
今回はOSI参照モデル レイヤ3 ネットワーク層のARP、DNSについてまとめました。
次回もレイヤ3 ネットワーク層についてまとめます。
最後に、記事を読んで間違いの指摘などがあればコメントで教えていただけると幸いです。
ありがとうございました。
Vertex AI Vector Search の DeployedIndex の index_sync_time を取得する

> To check whether the change has been propagated, compare the update index operation finish time and the DeployedIndex.index_sync_time

ref: https://cloud.google.com/vertex-ai/docs/vector-search/update-rebuild-index?hl=en

`Index` の更新が `DeployedIndex` に伝播されたかを確認するために `index_sync_time` を参照せよ、とのことだが具体的な参照方法が記載されておらず困った。

色々試してみた結果以下のようにすればよいことが分かった。
`DeployedIndex` を直接参照する方法が見つからなかったため、まず `IndexEndpoint` を取得し、`IndexEndponit` が持つ `deployed_indexes` を参照する形になっている。

```python
from google.cloud import aiplatform

INDEX_ENDPOINT_NAME='projects/xxxxxx/locations/xxxxxx/indexEndpoints/xxxxxx'
index_endpoint = aiplatform.MatchingEngineIndexEndpoint(
    index_endpoint_name=INDEX_ENDPOINT_NAME
)
index_sync_time = index_endpoint.deployed_indexes[0].index_sync_time
```




### P.S. 
> `DeployedIndex` を直接参照する方法はないため、まず IndexEndpoint を取得し、`IndexEndponit` が持つ `deployed_indexes` を参照する

`IndexEndponit` が持つ `deployed_indexes` の内容は以下のようになっている。

```python
from google.cloud import aiplatform

INDEX_ENDPOINT_NAME='projects/xxxxxx/locations/xxxxxx/indexEndpoints/xxxxxx'
index_endpoint = aiplatform.MatchingEngineIndexEndpoint(
    index_endpoint_name=INDEX_ENDPOINT_NAME
)
print(index_endpoint.deployed_indexes[0])
```
```
id: "xxxxxx"
index: "projects/xxxxxx/locations/xxxxxx/indexes/xxxxxx"
display_name: "xxxxxx"
create_time {
  seconds: 1733286121
  nanos: 942464000
}
index_sync_time {
  seconds: 1733366784
  nanos: 183820000
}
automatic_resources {
  min_replica_count: 1
  max_replica_count: 1
}
```

ちなみに `IndexEndpoint` ではなく `Index` からも `deployed_indexes` を参照できるが、ここには `index_sync_time` が含まれていなかった。
```python
from google.cloud import aiplatform

INDEX_NAME = "xxxxxx"
index = aiplatform.MatchingEngineIndex(index_name=INDEX_NAME)
print(index.deployed_indexes[0])
```
```
index_endpoint: "projects/xxxxxx/locations/xxxxxx/indexEndpoints/xxxxxx"
deployed_index_id: "xxxxxx"
display_name: "xxxxxx"
```
Windows10もサポート終了を迎えるというのに、ActiveXのせいでIEモードを脱却できないあなたへ

## はじめに
この記事は [NRI OpenStandia Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nri-openstandia) の5日目の記事です。

Windows10のサポート終了日（2025年10月14日）まで、残すところ1年弱となりました。

Windows11への移行を契機に、社内システムをEdgeIEモードからEdgeデフォルトモードへ移行するケースがほとんどかと思いますが、その一方で Windows11でもEdgeIEモードが利用可能なため、引き続きIEモードを利用する選択を取ったシステムもあるかと思います。

[Microsoftの発表](https://learn.microsoft.com/ja-jp/lifecycle/faq/internet-explorer-microsoft-edge
)によれば、IEモードは少なくとも2029年まではサポートされると明言されていますが、気が付けばあと5年もなく、2029年より先にサポートが延長される保証もありません。
ということでそろそろ重い腰を上げてIEモードを脱却するいいタイミングですが、腰を重くしている理由の一つに「ActiveX（ActiveXコントロール）」が…というシステムもあるのではないでしょうか。

今回は、私がこれまで経験したIEモード脱却のケースを振り返り、移行のハードルが高いと感じたActiveXの使われ方と、それに対しどのような移行策が考えられるかを整理したいと思います。

### パターン１：リッチなUIの作りこみ
リッチなUIを実現するためにActiveXを使っているケースがあります。
今でこそブラウザ標準のJavaScriptやCSSで様々なUIを表現できるようになりましたが、IEが全盛だった2000年代初頭などはまだブラウザ標準機能で表現できるUIには限界があり、このためにActiveXを利用しているケースが多くありました。

この場合は、素直にJavaScriptやCSSへの置き換えを考えるタイミングかと思います。
画面全体を再構築するのであればReactやVue.jsを使ったSPAに作り替えるのが無難な選択と言えそうです。それぞれのフレームワークで様々なUIコンポーネントライブラリが公開されており、リッチなUIを実現可能です。

部分的なUIコンポーネントとしてActiveXを使っている場合は、その部分だけ別のJavaScriptライブラリで代替するという案も考えられます。
たとえば、Excelの埋め込みなどMicrosoft Office製品との連携を密にやっている場合は、Wijmo のようなJavaScriptの世界でほぼExcelのUIを表現できてしまうライブラリの導入も選択肢として考えられます。

https://developer.mescius.jp/wijmo

### パターン２：クライアントアプリケーションとの連携
社内システムとして使うWindows端末では、ブラウザで操作するWebアプリケーションだけでなく、Windowsにインストールされたクライアントアプリケーションも併用して業務を行うケースがあります。

ActiveXは、クライアントにインストールされたモジュールをブラウザで読み込んで利用するというその特性から、クライアントアプリケーションとの連携が比較的容易に実現可能でした。
このパターンでは、単純にJavaScriptに移行しようと考えたとしても、セキュリティの観点からクライアントアプリケーションとの連携が容易ではないため、他の仕組みを併用して実現方法を考える必要があります。

基本的な方針としては、クライアントアプリケーションをサーバサイドへ移行し、システム間の連携はAPI等を介してサーバサイドで連携を行う、という形式に移行していくのが良いでしょう。
クライアントアプリケーションがなくなれば、端末配布に頭を悩ますこともなくなりますし、シンクライアントといったよりセキュリティ強度の高い端末でもシステムを利用できるようになります。

とはいえ、すぐにクライアントアプリケーションを無くせるかといったらそれも現実的ではないでしょう。当座をしのぐ意味でもクライアントアプリケーションとの連携は必要に可能性があります。

まず、ブラウザから端末内のクライアントアプリケーションへの連携を実現したい場合は、カスタムURIスキームを使ってアプリケーションを起動する方法が考えられます。

https://learn.microsoft.com/ja-jp/windows/uwp/launch-resume/launch-default-app

カスタムURIスキームはWindowsのレジストリへの登録作業が必要となりますが、これを利用することでブラウザから任意のアプリケーションを起動することが可能となります。

これとは逆に、他システムが連携元となって自システムである起動中のブラウザに連携を行いたい場合は、ブラウザに対しメッセージを送る仕組みを使って連携を行う必要があります。
連携元が同じブラウザであれば、JavaScriptのpostMessageを使うことで比較的容易に連携が可能です。

https://developer.mozilla.org/ja/docs/Web/API/Window/postMessage

クロスドメインの考慮は必要ですが、連携相手が互いに社内システムであればiframeで埋め込んでWindow間でメッセージを連携する、といった比較的密な実装を前提とした連携も選択肢としてはありかもしれません。

また、サーバを経由してブラウザへの連携が必要な場合は、その用途に応じてWebSocketやPush APIといった仕組みを利用することで実現が可能です。

https://developer.mozilla.org/ja/docs/Web/API/WebSocket

https://developer.mozilla.org/ja/docs/Web/API/Push_API

たとえばSpringBootでは WebSocket でインタラクティブな Web アプリケーションを作成するガイド が公開されていますので、SpringBootで構築済みのシステムであれば現状のシステム構成を変えることなく機能を追加できるかもしれません。

https://spring.pleiades.io/guides/gs/messaging-stomp-websocket

もちろん、複数の端末がサーバに接続してくるため「どの端末に通知を行うか」といった制御は考慮が必要です。

## おわりに
ActiveXは社内システムにとって多くのメリットを生み出してくれた機能ではありましたが、いよいよ卒業しなければならない時がやってきました。
古い技術からの脱却を新しいシステムへの再構築の機会ととらえ、この記事がActiveX脱却のきっかけになれば幸いです。
起業するならElixirシリーズSTEP8.品質を高めろ

https://qiita.com/Yoosuke/private/a189163acf8a1306df7a

前回はこちら

## プロトタイプから品質向上へ
プロトタイプを作り、顧客への価値提供を始めたら次のステージは品質向上です。最初の顧客はある意味パートナーであり、これまでにない問題解決ができれば、多少のサービス品質の低さは許容してくれるものです。

## 先行者の優位性と落とし穴
市場に前例のないサービスを提供する場合、比較対象となる品質基準がないため、その時点ではあなたが最高品質を提供していることになります。しかし、この状態に満足していると、後発企業に追い抜かれる可能性が高くなります。先行者は市場での優位性（先行者利益）を確保するまで、圧倒的な差をつけて逃げ切る必要があります。その差をつけるための施策が各社、戦略に基づいて変える必要がありますが、Qiitaは技術者向けのメディアなので、今回取り上げる戦略は「品質向上」をテーマにしたいと思います。

## 品質の本質を考える
品質とは単なる技術的な完成度ではありません。重要なのは「顧客が価値を感じるか」という点です。そこで、以下の3つの視点で品質を管理していく必要があります
1. 顧客は本当に価値を感じているか
2. 製品は確実に価値を届けられているか
3. チームは継続的に価値を提供できる体制になっているか

## 変化への対応力が生存の鍵
現代のソフトウェアサービスには、以下のような特徴があります
1. 生き物のように常に変化し続ける必要がある
2. 社会の変化のスピードが速い
3. 顧客ニーズが急速に変化する

このような環境で生き残るためには、変化に素早く対応できる製品・サービスを作る能力が不可欠です。まさに生物の「適者生存」と同じ原理が働くのです。

## Elixir

本日のElixirのコーナーはこちらをご覧ください。w

https://qiita.com/Yoosuke/private/5c94b892e053865be041
Amazon SageMaker AI ってなんですの？

2024年12月3日付けで「SageMaker」から「SageMaker AI」に改名しています。

個人的には結構慣れた名前だったので改名してそこそこ驚いています（Azureは「Azure AI Studio」を「Azure AI Foundry」という大胆な改名をしているのでそれよりかは全然覚えやすい）。

改名に関する公式の説明があったので紹介します。

https://docs.aws.amazon.com/sagemaker/latest/dg/whatis.html#whatis-rename

# Amazon SageMaker AI とは？

Amazon SageMaker AI は、完全マネージドの機械学習 (ML) サービスです。SageMaker AI を使用することで、データサイエンティストや開発者は、ML モデルを迅速かつ自信を持って構築、トレーニングし、本番環境に適したホスト環境にデプロイできます。SageMaker AI は、複数の統合開発環境 (IDE) にわたる ML ワークフローを実行するための UI 経験を提供し、ML ツールを利用可能にします。

SageMaker AI を使用すると、独自のサーバーを構築・管理することなくデータを保存・共有できます。これにより、組織や個人は ML ワークフローの共同作業と開発により多くの時間を割くことができ、早期に進めることが可能です。SageMaker AI は、非常に大規模なデータに対して効率的に動作するマネージド ML アルゴリズムを提供し、分散環境で動作します。また、独自アルゴリズムやフレームワークを使用できる柔軟な分散トレーニングオプションを備えています。SageMaker AI コンソールから数ステップで、安全でスケーラブルな環境にモデルをデプロイできます。



## トピック

- Amazon SageMaker AI の改名
- Amazon SageMaker と Amazon SageMaker AI
- Amazon SageMaker AI の料金
- 初めて Amazon SageMaker AI を使用する際の推奨事項
- Amazon SageMaker AI を使用した機械学習の概要
- Amazon SageMaker AI の機能

---

## Amazon SageMaker AI の改名

2024 年 12 月 3 日に、Amazon SageMaker は Amazon SageMaker AI に改名されました。この名称変更は、既存の Amazon SageMaker の機能には適用されません。

### レガシーネームスペースは変更されません

以下の sagemaker API ネームスペースおよび関連ネームスペースは、後方互換性を保つために変更されません：

- AWS CLI コマンド
- AmazonSageMaker プレフィックスを含むマネージドポリシー
- sagemaker を含むサービスエンドポイント
- AWS::SageMaker プレフィックスを含む AWS CloudFormation リソース
- AWSServiceRoleForSageMaker を含むサービスリンクロール
- sagemaker を含むコンソール URL
- sagemaker を含むドキュメント URL

---

## Amazon SageMaker と Amazon SageMaker AI

2024 年 12 月 3 日、Amazon は次世代の Amazon SageMaker をリリースしました。

Amazon SageMaker は、データ、分析、および AI のための統合プラットフォームです。AWS の機械学習および分析機能を統合し、すべてのデータに統一されたアクセスを提供することで、分析と AI の統合されたエクスペリエンスを提供します。

### Amazon SageMaker の機能

- **Amazon SageMaker AI** (旧称 Amazon SageMaker)：完全マネージドのインフラストラクチャ、ツール、およびワークフローを使用して ML モデルおよび基盤モデルを構築、トレーニング、デプロイ
- **Amazon SageMaker Lakehouse**：Amazon S3 データレイク、Amazon Redshift、その他のデータソースを横断するデータアクセスを統一
- **Amazon SageMaker Data and AI Governance**：Amazon DataZone を基盤に構築された Amazon SageMaker Catalog を使用して、データと AI を安全に発見、管理、共同作業
- **SQL Analytics**：Amazon Redshift を使用した最も費用対効果の高い SQL エンジンでのインサイトの獲得
- **Amazon SageMaker Data Processing**：Amazon Athena、Amazon EMR、および AWS Glue のオープンソースフレームワークを使用して、データの分析、準備、統合
- **Amazon SageMaker Unified Studio (プレビュー)**：すべてのデータおよび分析と AI のためのツールを 1 つの開発環境で構築
- **Amazon Bedrock**：生成型 AI アプリケーションを構築およびスケール

詳細については、[Amazon SageMaker](https://aws.amazon.com/sagemaker) を参照してください。


## Amazon SageMaker AI の料金

AWS 無料利用枠の制限および SageMaker AI の使用に伴うコストに関する詳細は、[Amazon SageMaker AI の料金](https://aws.amazon.com/sagemaker/pricing/) を参照してください。
特徴量エンジニアリング　4日目

今日は

https://www.kaggle.com/code/ryanholbrook/principal-component-analysis

を読んでいきましょう
このtutorialは主成分分析という取り組みについてです。つまりあるデータの成分の重み付き和でどの程度もとのデータを説明できるか、また、ほとんど相関していないデータなどを削除し、より少数の成分でもとのデータを説明できるかを考えていきます。
コースのはじめの方に

Technical note: PCA is typically applied to standardized data. With standardized data "variation" means "correlation". With unstandardized data "variation" means "covariance". All data in this course will be standardized before applying PCA.)


[DeepLによる日本語訳]
(技術的注意：PCAは通常、標準化されたデータに適用されます。標準化されたデータでは、「ばらつき 」は 「相関 」を意味する。標準化されていないデータでは、「ばらつき 」は 「共分散 」を意味する。このコースのすべてのデータは、PCAを適用する前に標準化される)。

DataScienceでは標準化する必要があることを述べています。
これは高校数学統計分野での分散を１にしたり平均を0にしたりという作業であり

```
# Standardize
X_scaled = (X - X.mean(axis=0)) / X.std(axis=0)
```

です。このコードは数学で学んだ式そのものです。

その後いくつかのコードが続きます

fit_transform()でPCAの学習と変換を同時に行います
返り値は主成分空間に変換されたデータ（numpy配列）
pcaに渡すデータは標準化とfit_transform（）したものを渡すこと
```
X_pca = pca.fit_transform(X_scaled)
```

pca.components_について
各行は1つの主成分を表し、各列は元の特徴量に対する重みを表します
ある成分の相関係数の集まりと捉えてください。
絶対値が大きいほど、その特徴量の影響が強いことを意味し、符号は方向を示します（正か負か）
正でも負でも、絶対値が大きければ元のデータを説明できるようになることにかわりはありません。
全ての成分の2乗の和は1となります。

tips!!

- loadingsと出てくる英語ですが、意味は「負荷量」です。相関係数と同じ意味合いで使われています。
- pca.components_.Tと転置してますが見やすくしているだけで他の要件はありません。
ターミナルにドット絵を表示する

# ターミナルにドット絵を表示する方法
CUIのコンソールにドット絵を表示する方法についてのメモ

## 背景色を使う
調べるとよく出てくる方法
エスケープシーケンスを使用して背景色を指定します。
``` diff:メリット・デメリット
+ カラフルなドット絵を表示できる
- 表示スペースが大きくなる
```
![スクリーンショット 2024-12-04 125332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3696110/eb8733a8-b00c-61da-0209-14428098e787.png)

エスケープシーケンスについては[この記事(Qiita)](https://qiita.com/PruneMazui/items/8a023347772620025ad6)を参考
## 点字を使う方法
紹介してる記事がほとんど見つからない
``` diff:メリット・デメリット
+ １行に４ドット表示可能
- ドットごとに色を設定できない
- 表示環境によっては4ビットごとに隙間が発生
```
![スクリーンショット 2024-12-04 125332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3696110/850630eb-742e-3b26-af33-30814f4c8867.png)

### 点字ドット絵の実装方法
点字はUnicodeから作成すると簡単
ドットの有無を2進数で表現し、ベースとなる0x2800に2進数を加算
```　.ビットの位置
・・　　０３
・・　　１４
・・　　２５
・・　　６７
```
``` 例.
 文字コード　ベース      76543210
⣿ 0x28FF <= 0x2800 + 0b11111111
⣴ 0x28FE <= 0x2800 + 0b11111110
⠋⠀0x2813 <= 0x2800 + 0b00010011
```
文字列配列から点字に変換するサンプル
``` sample.py
def draw(pattern, W, H):
    key = [
        [0, 3],
        [1, 4],
        [2, 5],
        [6, 7]
    ]
    # 配列を初期化
    output = [[0 for _ in range((W + 1) // 2)] for _ in range((H + 3) // 4)]

    for h in range(H):
        for w in range(W):
            if pattern[h][w] == 'o':
                output[h // 4][w // 2] += 2 ** key[h % 4][w % 2]

    BASE = 0x2800
    for raw in output:
        for c in raw:
            print(chr(BASE + c), end='')
        print()


# 使用例
pattern = [
    "  oo  ",
    " o  o ",
    "o    o",
    "o    o",
    " o  o ",
    "  oo  ",
]
W = 6
H = 6

draw(pattern, W, H)
```
```
$ python3 sample.py
⡔⠉⢢
⠈⠒⠁
```
## まとめ
- 2色のドット絵を表示するなら点字を活用するのもアリ
[Smartsheet]Core Product Certification合格体験記

# はじめに
Qiita advent Calender19日目です。
記事を書きながら、試験を今月3つ受けました。
マジで危なかったです。
そんな、Smart Sheetの合格方法について記載します。

# Smartsheetとは
以下記事を読んでください。
いわゆるタスクマネジメントツールですが、勉強するとかなりすごいツールだと感じました。
2023年、日本に本格的参戦を果たしているので、これからはやるのではないかと思います。

https://qiita.com/WeedMashroom/private/0fdc931fc96431fe592a


# Core Product の結果
合格点が、44/60　取得点数も44/60ということでかなり危ない点数でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3296700/f1446083-4361-2ced-e29f-e737b557237e.png)

# この試験の難しさ

**過去問の不足**：過去問が全く存在せず、公式が用意している40問も全て英語で記載されているため、準備が難しい。
**新しい試験**：この製品が日本で流通し始めたのが2023年で、まだ勉強するためのリソースが少ない。
**英語のみの試験**：試験は英語でしか受けられず、90分の制限時間内で問題文を理解し解答するのが難しい。

# 勉強方法

以下のページにある「Smartsheet Core App」のラーニングパスを受講してみてください。これを完了するだけで認定証がもらえます。

特に、このチュートリアルは日本語の映像版が用意されているので、内容を理解するためにはこの動画を見ることをお勧めします。ハンズオンやミニテストなどが難しい部分もありますが、これをクリアできれば、内容の約6割を理解したと考えて良いでしょう。

https://smartu.smartsheet.com/path/self-paced-core-app-learning-path-japanese

上記資格を取った後に、お勧めするのが、こいつです。

https://smartu.smartsheet.com/core-product-certification-exam

テストの出題範囲について詳しく教えてくれる資料があるので、それをしっかり理解することが重要です。以下のポイントを参考にしてみてください：

**出題範囲の理解**：資料を活用して、出題範囲をしっかりと把握し、書いてある内容を理解するように勉強しましょう。

**数式の得点源化**：このテストでは数式の部分で多くの点を取ることが可能です。エクセルに似ている部分があるので、エクセルの知識を活かして得点源にしましょう。

**英語の形で覚える**：英語が苦手な場合は、形で覚えることも一つの方法です。中学で習ったSVOCのような基本構文を理解しておくことが重要です。

**英語力の重要性**：英語の力が試験に大いに役立ちます。英語の基礎がわからない場合、このテストは難しいかもしれません。その場合、他の方法で英語力を高めることを検討してみてください。

 質問があれば、ください
【TypeScript】タプルの長さを返す型の実装（type-challenges 初級編 18・Length of Tuple）

## お題
タプル`T`を受け取り、そのタプルの長さを返す型`Length`を実装する。

## やりたいこと
```typescript
type member = ["Tom", "John", "Mike"];
const color = ["red", "blue", "green", "yellow", "purple"] as const;

type memberLength = Length<member>; // 3
type colorLength = Length<typeof color>; // 5
```

## 解答
```typescript
type Length<T extends readonly any[]> = T["length"];
```

## 解説

### 処理の流れ
- `<T extends readonly any[]>`
Tが読み取り専用の配列のみを受け取るように制約。
- `T["length"]`
`["length"]`を使用し、タプルの要素の数を取得。

### 配列型の要素の数を取得するには...
`["length"]`を使用する。
```typescript
type member = ["Tom", "John", "Mike"];
type memberLength = member["length"]; // 3
```

### constアサーションとは...
https://qiita.com/yuto99999/items/44161921ff23a149cba5#const%E3%82%A2%E3%82%B5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3as-const%E3%81%A8%E3%81%AF

### typeof演算子とは...
https://qiita.com/yuto99999/items/44161921ff23a149cba5#typeof%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%A8%E3%81%AF

## 参考記事
https://mosya.dev/blog/tc-tuple-length

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/00018-easy-tuple-length/README.ja.md#length-of-tuple--
APIのパフォーマンス改善について

これは[Hubble Advent Calendar 2024](https://qiita.com/advent-calendar/2024/hubble)の6日目[^1]の記事です。

# はじめに
こんにちは、バックエンドエンジニアの@yamaopankuです！
[株式会社Hubble](https://hubble-docs.com/)さんにて2024年10月より業務委託として参画させていただいております。

Hubbleではバックエンド・DBはそれぞれRuby on Rails 7系、MySQL （AuroraDB）8系で構成されており、Angularで構成されたフロントエンドからAPIのリクエストを受けます。

今回はJOINしてから行ったAPIのパフォーマンスチューニングに関して記事を書いていこうと思います！

# 取り組んだ課題
Hubbleは契約書管理のSaaSでWordやPDF、EXCELなどの契約書を一元管理できます。
それぞれの契約書に関し、契約書名や契約相手方、契約開始日などの項目を設定可能であり、登録した契約書とその項目値を一覧表示し、項目値で検索できる機能があります。(ドキュメントリストといいます)

とても便利でユーザからも好評な機能ですが、データ量の増加に伴い検索のAPIパフォーマンスが課題として挙がってきており、レイテンシの向上に向けて取り組むことになりました。(p90で18s、AVGで7sほど)
![スクリーンショット 2024-12-04 17.32.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423574/06786d60-7ba9-734c-253c-c071013ce281.png)

# 解決に向けてのアプローチ
## ボトルネックの把握
HubbleではDatadogを導入しているため、まずはAPMで該当APIのリクエストのflamegraphからボトルネックになっていそうな箇所を把握するところから開始しました。

すると、一つのSQLが80%近くを占めていることがわかりました。
以下のようなイメージのSQLです。
table_aが契約書に設定できる項目であり、契約書 : table_aは1 : Nとなっています。
```
SELECT
    table_a.x_id,
    table_a.y_id,
    table_a.z_id,
    table_a.value
    table_a.s_id
FROM
    table_a
    ...
    INNER JOIN
        (
            SELECT
                table_a.*
            FROM
                table_a
            WHERE
                table_a.s_id = ?
        ) AS table_a_001
    ON  (
            table_a.row_id = table_a_001.row_id
        )
    ... 指定した項目数だけtable_aの自己結合(INNER JOIN or LEFT OUTER JOIN)
WHERE
    table_a.x_id IN(サブクエリ)
AND table_a.s_id IN(サブクエリ)
AND (
        table_a_001.column_id = ?
		AND table_a_001.value LIKE ?
    )
... 指定した項目数だけtable_aの条件をANDで繋ぐ
```

「推測するな、計測せよ」という金言に則り、EXPLAINで実行計画を見ると、テーブルアクセスがサブクエリ + 指定した条件数分だけ行われていることがわかります。

また、MySQL 8.0.18以降はEXPLAIN ANALYZEを使用し、より詳細な実行計画を見ることができ、ステップごとの実行時間を見ることができるため、合わせて確認しました。
EXPLAIN ANALYZEは[こちらの記事](https://qiita.com/Nyokki/items/c2d95cb2a75d3c0acb64)がわかりやすくておすすめです。


EXPLAIN ANALYZEで実行計画を見ると、`Nested loop inner join`の箇所で時間を要しており、自己結合の箇所が改善ポイントと特定しました。

## 解決策
自己結合している理由としては、同じ契約書について複数の項目で条件を絞り込んでいることが背景のため、項目テーブル(先のtable_a)で契約書単位にGROUP BYすれば一度のテーブルアクセスで済むのではと考えました。
次のようなクエリのイメージです。
```
SELECT
    ...
FROM
    table_a
WHERE
    s_id IN(指定した項目ID)
    AND x_id IN(絞り込み対象の契約書ID)
GROUP BY
    x_id
HAVING COUNT((s_id = ? AND 条件) OR NULL) > 0
... 指定した項目数だけ同様のCOUNTの条件を作り、ANDで繋ぐ
```

絞り込みとGROUP化対象のカラムでインデックスが使えるよう、s_idとx_idの複合インデックスを作成の上、実行すると変更前と比較し、18s → 3.5sと向上に成功しました。
(理想は1s未満ではありますが...)
EXPLAINによる実行計画もtable_aへのテーブルアクセス1回のみになりました。

# 今後の取り組み
今回以外のAPIでもまだまだパフォーマンスを上げていけそうなものがあるため、リクエスト数やレイテンシを日々観察しながら調査・対応していきたいと考えています。
また、Hubbleでは一部の機能でOpenSearchも利用しているため、SQLチューニングのみでの解決が難しくなってきたら更なる活用も検討していきたいと思います。

# まとめ
この記事では、実行計画をもとにしたSQLチューニングに関して改善に向けて行動したことを書いてきました。
MySQL 8.0はまだ使い始めた段階のサービスが多いと感じており、運用面で課題になることもあると思いますが、EXPLAIN ANALYZEをはじめとした有益な変更もあるため、今後の展望に期待したいですね。

この記事がパフォーマンス改善に取り組む方にとって少しでも参考になれば幸いです。

明日は@power3812の投稿です！

[^1]: 平日のみの投稿なので、投稿日は9日ですが6日目の記事としています。
【ML初心者アドベントカレンダー】データ形式のタイプについて学ぶ


# この記事の目的

データのタイプについて説明できるようになる。

---

そもそもデータとは…
　モデルの学習に使用する素材。一口にデータといってもたくさんタイプがあり、それぞれに適応するべきアルゴリズムも違うので簡単にまとめる。



# ラベル付きデータ

データに対する正解（ラベル）が明確に定義されたデータのこと。<a href="https://qiita.com/ei_540/items/289f8ab20f48eac48e20#%E6%95%99%E5%B8%AB%E3%81%82%E3%82%8A%E5%AD%A6%E7%BF%92supervised-learning">教師あり学習</a>で使用される。
「犬というラベルがついている犬の画像」などが例。


# ラベルなしデータ

正解がないデータのこと。<a href="https://qiita.com/ei_540/items/289f8ab20f48eac48e20#%E6%95%99%E5%B8%AB%E3%81%AA%E3%81%97%E5%AD%A6%E7%BF%92unsupervised-learning">教師なし学習</a>で使用される。
ラベルが付いていない犬の画像や、風景写真などが例。


# 表形式データ

行と列のテーブルみたいな表で構成されるデータ。回帰問題や分類問題で用いられる。（一番一般的なデータ形式らしい）
体重や身長などを含んだ健康診断のデータなどが例。


# 時系列データ

時間の経過により変わっていくデータのこと。
株価や日々の体重の変化などが例。

# 画像データ

その名前の通り、画像ベースのデータのこと。処理をするときはピクセルに変換される。


# テキストデータ

その名前のとおり、文字で表現されるデータのこと。メールや記事が例。
自然言語処理で使用される。

## 自然言語処理（NLP）とは

人間が会話で使うような言葉を意味や解釈も含めてAIに学ばせること。
チャットポットなどに使われている。

# 構造化データ

わかりやすい形式をもち、格納されたデータのこと。データベースに保存され、クエリを適用できるものなどが当てはまる。
Parquet などが例。


# 非構造化データ

構造化データとは違い、特に形式のないデータのこと。画像データとかもそう。
決まった形式がないので処理が難しく、クエリも使えない。


# ざっくりまとめ


**ラベル付きデータ**
 正解（ラベル）とセットのデータ

**ラベルなしデータ**
　特に正解を持たないデータ

**表形式データ**
　行と列をもった表形式のデータ

**時系列データ**
　時間により変化するものを扱ったデータ
 
**画像データ**
　画像をベースとしたデータ

**テキストデータ**
　文章をベースとしたデータ

**構造化データ**
　決められたスキーマをもつデータ。

**非構造化データ**
　決められた構造を持たないデータ。
ソラカメでPoE接続

# 概要
SORACOM社が提供するクラウドAIカメラ「ソラカメ」は、
通常WiFiでインターネットに接続して利用しますが、
2024年8月にソラカメを有線で接続できるケーブルが公式に提供開始されました。
⇒[https://www.soracom.com/ja/news/20240826-lan-adapter-for-cloud-camera](https://www.soracom.com/ja/news/20240826-lan-adapter-for-cloud-camera)

このケーブルを使って、ソラカメをPoE接続で動かしてみようと思います。

# 準備するもの
・ATOM Cam 2
![ソラカメ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/c1cee67a-92df-e730-44c0-aa70242dc0ed.jpeg)


・ATOM Cam 2 専用 LANアダプター
![processed-87141B09-D895-4D80-B22E-4D4C2D5F79DC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/4b35dda8-a879-fa52-a104-7f74562509c2.jpeg)

・PoE ハブ（今回はTP-Link社製 TL-SG1005Pを使用）
![processed-4FD9B6A3-A99D-4AB0-8AC2-446C039A0C0C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/e20b1eef-dfe7-882d-8d06-ce92c0eae0f2.jpeg)

・PoE スプリッター（今回はRevotech社製 USB0503Gを使用）
![processed-9029C2C8-61F5-43B6-95FA-DC1D88462CA7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/d0923231-8892-4115-b944-3ff9b0b52a20.jpeg)

・LANケーブル（Cat5e以降のケーブル）

# 手順
## 有線接続
PoEを試す前に、まずはソラカメの有線接続を確認してみました。
接続イメージはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/e96acf64-781e-3f8f-3128-c2feedf9c3b5.png)

一応念のために、ソラカメのファームウェアを最新版にアップデートしてから確認しました。

Atom Camのアプリにどうやって有線で認識させるのかなと思ったのですが、
通常のカメラ登録時に、「存在しないSSID・パスワードでQRコードを生成させる」という手順を踏みます。
![Image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/6bb84fbf-be8c-393f-4d95-7d4a8b833743.jpeg)

存在しないSSIDを設定しても、有線LANでの接続ができると、そのまま登録が完了します。


## PoE接続
次にPoE接続の確認に移ります。
接続イメージはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/2acc4c44-fdee-db40-b9fa-17ef811f347d.png)


実際はこんな感じ（笑）。
![Image (002).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/13926b20-ecf9-3bb3-ae14-daf08bc56455.jpeg)

有線LANでの接続に成功していれば、特に何の設定変更も行わず、
そのままPoE接続にするだけで接続ができました。
ケーブルさえ間違わなければ難しいことは何も無いです。

# まとめ
発売されてから、さまざまなユースケースが出てきた中で、
WiFi環境以外での使い方もできるようになったソラカメ。

PoEスプリッターを使えば、PoE接続環境でも使えることを確認できました。
PoEスプリッターも安く調達できるので、現状のPoE接続環境に
簡単にソラカメを導入できますね！

ATOM Cam 2専用のPoEアダプターが販売されたら
さらに使い勝手が良くなりそう。
ソラコムサンタにお願い・・・かな（笑）。
【三周開発】おなじアプリを３周して、しなやかで強いプログラマになる

## はじめに
技術力がついてきた、と感じる瞬間はいつでしょうか？

わからないところがない、決まっていないことがない状態。
完了までの解像度が高い状態。

つまり **「あとはコードを書くだけ」** になっていることではないでしょうか。
（そしてコードも頭の中にイメージできている! :clipboard: ）


では、この状態を体験するには何をすればいいのでしょうか。
今回は、「おなじアプリを3周する」というアプローチで、設計力や実装力、作業効率化のノウハウを体系的に高める方法をまとめます。

## 学習の5段階について

:::note warn
おなじアプリを3回もつくるのはさすがに退屈では？
:::

ソフトウェアの作り方に正解がないように、おなじものを作っても完成までの道筋は無限です。
どのルートを通ると最適なのか、どの道具を持っておくとラクに成果がだせるのか、考え方をアップデートしながら周回するので退屈はしません。

以下にまとめている「学習の5段階」を念頭におくと、1周目〜3周目までのねらいが違うので初学者には特に効果的な取り組みだと考えられます。

> レベル１：無意識的無能
知らないからできない

> レベル２：意識的無能
知っているけどできない

> レベル３：意識的有能
意識すればできる

> レベル４：無意識的有能
意識しなくてもできる

> レベル５：無意識的有能に意識的有能
人に教えることができる

引用元

https://note.com/kshirakami/n/na4ee1df3ca09



## お題「ミニブログ」
お題となるアプリの要件は以下にまとめます。

### ＜主な機能＞
1. ユーザー登録ができる
1. 短文のCRUDがある
1. 投稿とユーザー情報が紐付くようにする
1. ログインすると短文を投稿できるようになる

### ＜基本要件＞

- 投稿文字数は140字に制限
- 投稿内容は「全体タイムライン」に表示される
- 表示する内容は以下
    - 投稿内容
    - 投稿時間（YYYY/MM/DD hh:mm）
- ログイン情報
    - ユーザー名（半角英数字のみ、スペース禁止、20文字以内）
    - パスワード
- ユーザー情報
    - 非公開情報
        - パスワード
    - 公開情報
        - ユーザー名
        - プロフィール（200文字以内）
- 公開情報は各ユーザーのプロフィールページから閲覧することができる

### ＜その他＞
- ビューの記述にはHaml記法をつかう
- CSSテンプレートとして bootstrap をつかう
- ユーザーの認証には devise をつかう


## 1回目の開発

- 知らなかったことを知る
- できることが増える

まずはアプリケーションを最初から最後まで完成させます。このステップでは、アイデアを形にする力を養うことが目的です。途中でつまずいた部分や手間取った部分をメモしておき、次回以降に改善の余地を探ります。完成までの時間を計測し、後の反復に活かします。

## 2回目の開発
- さらに知っていることを増やす
- よりスムーズにできることが増える

1回目で得た経験をもとに、2回目では開発時間を半分に短縮することを目指します。このステップでは、再利用可能なコードの設計や、開発フローの効率化に焦点を当てます。また、1回目で気づいた改善点を反映し、完成度をさらに高めることを目標とします。

## 3回目の開発
- 意識しなくてもできることが増える
- これまで知らなかったことを探しにいく

最後の反復では、さらに短時間での完成を目指すか、あるいは技術や要件に変化を加えてトライします。たとえば、フレームワークやライブラリを変える、MVP（最低限の製品）の要件を一層簡素化するなど、多角的なアプローチを試します。このプロセスにより、柔軟な開発能力や新たな視点が得られます。

## おわりに
おなじアプリを3周することで、技術力と開発スピードが確実に向上します。一度で終わる開発では得られない深い学びを体感し、自信を持って新しいプロジェクトに挑むことができるでしょう。

TIPSでいうテクニックとスピードに効きますし、3周目はインテリジェンスの部分もイメージしながら取り組めると最高です。

https://kuranuki.sonicgarden.jp/archives/6051


ここで紹介したのは、学習の5段階について「知らない」→「できる」をぐるぐる回しながら技術力と思考力を伸ばしていく取り組みでした。

スキルセットとマインドセットは両輪で考えて行く必要がありますし、実務においてひとりひとりが能動的に動けるようになると、しなやかで強いチームに近づけると考えています。

## + 1 commit : セルフマネジメントにおける5段階ロードマップ
私たちソニックガーデンが考えるセルフマネジメントについても5段階ロードマップがありますので併せて紹介します。
新入生はLv1をしっかり続けていくことがたいせつです。こちらもご覧ください！


https://kuranuki.sonicgarden.jp/archives/31016
GitHub Actionsで手軽にカバレッジを行単位で可視化する方法

## はじめに

以前、以下の記事でカバレッジ可視化の方法を紹介しました。

[Ruby \+ GitHub Actions \+ reviewdogでカバレッジを行単位で可視化する](https://zenn.dev/aki77/articles/fb3a624709a47f)

ただし、以下のような課題がありました。

- Rubyに依存している
- セットアップが煩雑
- プルリクエストで変更のある箇所しかレポート対象とならない

これらの課題を解消するため、よりシンプルで依存の少ないGitHub Actionsを作成したので紹介します。

[aki77/reviewdog\-action\-code\-coverage](https://github.com/aki77/reviewdog-action-code-coverage/tree/main)

![68747470733a2f2f692e6779617a6f2e636f6d2f61613161326235353539636638336461326232333135656636613864373862352e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781/8ca29f85-07d6-c241-4e81-2ca853fc9528.png)

## 特徴

### シンプルな設定
`lcov`ファイルのパスを指定するだけでセットアップ完了。依存関係もなく、幅広いプロジェクトで活用できます。

### 並列実行されたテストもサポート
パス指定でglobパターンをサポートしており、複数の並列テスト結果もマージしてレポート可能です。
並列実行を行う大規模プロジェクトにも最適です。

### Reviewdogとの連携
[reviewdog](https://github.com/reviewdog/reviewdog)の仕組みに乗っかる形でカバレッジの可視化を行います。
これにより、GitHub Pull Request上で直感的に問題点を確認できます。

### テストカバレッジを直感的に把握できる
コードレビュー時に、 どの部分にテストが書かれていて、どの部分に書かれていないのかを一目で確認可能となります。
これによりレビューの質が向上し、カバレッジを意識したコーディング文化を醸成できます。

### Rustで作成したシングルバイナリでlcovファイルを変換
lcovファイルをReviewdog対応のcheckstyleフォーマットに変換するシングルバイナリを別途作成しました。
Rust製であるため、実行が高速でどのプラットフォームでも動作します。
[aki77/lcov\_to\_checkstyle](https://github.com/aki77/lcov_to_checkstyle)

## 導入手順

以下の設定例を参考に設定追加するだけで、行単位のカバレッジレポートがPull Request上で確認できるようになります。

```coverate.yml
name: Code Coverage
on: [pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Tests
        run: |
          # テスト実行とlcovファイル生成
          npm run test --coverage

      - name: Report Coverage
        uses: aki77/reviewdog-action-code-coverage@v2
        with:
          lcov_path: coverage/lcov.info
```

### サポートしているInputパラメータ

| パラメータ名 | 説明 | 初期値 | 必須 |
| - | - | - | - |
| `github_token` | GITHUB_TOKEN | `${{ github.token }}` | no |
| `lcov_path` | Lcovファイルのパス。（globパターンをサポート） |  | yes |
| `reporter` | reviewdog commandに渡すreporterオプション [github-check,github-pr-check,github-pr-review]. | `github-pr-review` | no |
| `tool_name` | reviewdog reporterの名前 | `code-coverage` | no |
| `delete_previous_comments` | 繰り返し実行された場合に過去のレポートコメントを削除するかどうか | `true` | no |

## おわりに
[octocov](https://github.com/k1LoW/octocov)と組み合わせることで、外部サービスなしでも効率的にカバレッジを計測・可視化できます。

特に以下のポイントが魅力です。
- 余計なライブラリやサービスに依存しない
- 高速で軽量なRust製ツール
- GitHub Pull Request上で直感的にカバレッジを確認可能

よかったらプロジェクトに導入してみてください。