OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby学習メモ（初学者向け）①


# Ruby学習メモ（初学者向け）

どうも、nus4です。

この度Ruby学習を始めました。  
この記事では、学習中に得たRubyの基本文法をアウトプットとしてまとめたいと思います。

## 学習方法

- Progate Rubyコース  
  （初めて有料プランを使いましたが、使いやすくておすすめです！）

## 📝 目次
- [コンソールへの文字列の出力](#コンソールへの文字列の出力)  
- [文字列内に変数を含めて出力](#文字列内に変数を含めて出力)  
- [条件分岐の書き方](#条件分岐の書き方)  
- [論理演算子の書き方](#論理演算子の書き方)  
- [配列の書き方](#配列の書き方)  
- [特定の要素をコンソールへ出力](#特定の要素をコンソールへ出力)  
- [配列の要素の数だけ処理を実行](#配列の要素の数だけ処理を実行)  
- [ハッシュの書き方](#ハッシュの書き方)  
- [ハッシュを用いた真偽値の判定](#ハッシュを用いた真偽値の判定)  
- [要素がハッシュである配列の書き方](#要素がハッシュである配列の書き方)  

## コンソールへの文字列の出力
```ruby
puts "文字列"
```
数値の場合は"不要

## 文字列内に変数を含めて出力
```ruby
puts "文字列 #{変数名}"
```

## 条件分岐の書き方
```ruby
if 条件式
    処理
elsif 条件式
    処理
else
    処理
end
```
条件式では()とthenを省略できるみたいです

## 論理演算子の書き方
```ruby
# かつ(AND)
A式 && B式

# または(OR)
A式 || B式
```

## 配列の書き方
```ruby
# 配列の宣言
配列名 = [要素1, 要素2, 要素3…]
```

# 特定の要素をコンソールへ出力
```ruby
puts 配列名[要素番号]
```
配列名は複数形にするのが一般的

## 配列の要素の数だけ処理を実行
```ruby
配列名.each do |変数名|
    処理
end
```
変数名は反対に、配列名の単数形にするのが一般的

## ハッシュの書き方
```ruby
# ハッシュの宣言（例：2要素）
ハッシュ名 = { "キー１" => "値1", "キー2" => "値2" }

# ハッシュの要素を更新
ハッシュ名["キー3"] = "値3"

# ハッシュの要素をコンソールへ出力
puts ハッシュ名[:キー]
```
キーに紐づく値を変数に持つことができる

## ハッシュを用いた真偽値の判定
```ruby
if ハッシュ名[:キー]
    処理
end
```
キーに対する値なし(nil)の場合は、false判定となる

## 要素がハッシュである配列の書き方
```ruby
# 要素がハッシュである配列の宣言 
配列名 = [
    {キー1: 値1, キー2: 値2},
    {キー1: 値1', キー2: 値2'}
] 

# 1要素をハッシュ変数に代入
ハッシュ名 = 配列名[要素番号]

# 1要素をコンソールに出力
puts 配列名[要素番号][:キー]
```

---  

少しでもお役に立てれば嬉しいです！  
Ruby初学者の方、一緒に頑張りましょう！💪
しつこい docker ビルドのキャッシュをクリアする方法

# 概要

docker ビルドをした際に「更新したはずのファイルがコンテナ上に反映されない」と苦しむことがあります。これは Dockerfile の `COPY` や `ADD` などでホストマシンのファイルをコンテナ上にコピーする際に、docker のビルドキャッシュが効いてしまって更新が反映されない現象です。

通常は `docker compose build --no-cache` でビルドし直せばいいのですが、これだけでは消えてくれないやっかいな場合があります。

### docker のビルドキャッシュについて

docker はビルドの各ステップをキャッシュしており、Dockerfile の命令に変更がない場合、キャッシュされたレイヤーを再利用します。これによりビルド時間を短縮できる一方で、ファイルの内容が変更されていても、Dockerfile の命令自体が変わらないとキャッシュが再利用され、変更が反映されないことがあります。

# docker のビルドキャッシュをクリアする方法

自分は以下の手順でやっています。

```bash
# まず docker コンテナを落とす
docker compose down
# docker のビルドキャッシュを消す
docker builder prune --all
# 念のため --no-cache でビルドしなおす
docker compose build --no-cache
# docker コンテナを立ち上げる
docker compose up -d
```

# 最強の魔法

上記の方法でビルドキャッシュは消せるはずですが、その他のキャッシュが効いて上手く反映されないこともあるかもしれません。「もう面倒臭いから全てのキャッシュを吹き飛ばしたい！」という方は以下を唱えてください。

```bash
docker system prune -a
```

これは以下のものを削除するので注意してください。

* 停止しているコンテナ
* どのコンテナも使用していないネットワーク
* 使われていないイメージ
* ビルドキャッシュ
* 使われていないボリューム

自分はイライラしてたまにこのコマンドを実行するのですが 5GB くらいスペースが空くので気持ちが良いです。
M5SatmpS3、8x8 Puzzle Unit (Unit Puzzle ?)で「あ、埼玉」とスクロール表示。


参考
----

https://github.com/Tamakichi/Arduino-misakiUTF16


いろいろ、注意
----

- 過去ログを見よ!!!
- M5Stack by M5Stack official 2.1.4

結果
----

![image_original(32).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f05c605f-1111-46bc-8a9d-5ab1bd9a1e41.jpeg)


プログラム
----

```c++


//NeoPixel8x8_kanji_scroll_M5StampS3_1


//インクルド
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <misakiUTF16.h>


//定義
#define MAX_X 8
#define MAX_Y 8
#define NUM_LEDS 64
#define RGBLED_OUT 13
Adafruit_NeoPixel strip(NUM_LEDS, RGBLED_OUT, NEO_GRB + NEO_KHZ800);

unsigned char Pixel[8][8][3];  //キャラクターRAM(カラー)

long s_buff[8];


void kanji_scroll_clr() {
  for (int i = 0; i < 8; i++) {
    s_buff[i] = 0;
  }  //for
}  //kanji_scroll_clr

void kanji_scroll_set(unsigned char *font) {

  for (int i = 0; i < 8; i++) {
    int a;
    a = s_buff[i] & 0xff00;
    a = a | font[i];
    s_buff[i] = a;
  }  //for
}  //kanji_scroll_set

void kanji_scroll_1up(unsigned char *font) {
  for (int i = 0; i < 8; i++) {
    s_buff[i] = s_buff[i] << 1;
    font[i] = s_buff[i] >> 8;
  }  //for
}  //kanji_scroll_1up

//void font_data_out(unsigned char *font){
//    for(int i=0;i<8;i++){
//        printf("[%02x]\n",font[i]);
//    }//for
//    printf("\n");
//}//font_data_out


//ネオピクセルに転送後に表示
void NeoPixe_OUT() {

  int k = 0;
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {

      strip.setPixelColor(k++, strip.Color(
                                 Pixel[y][x][0], Pixel[y][x][1], Pixel[y][x][2]));

      //Serial.print('.');

    }  //for j
    //Serial.println();
  }  //for i
  //Serial.println();

  strip.show();

}  //NeoPixe_OUT


//8x8文字の表示
void ch_8x8_f(unsigned char *font, int c1, int c2, int c3) {

  int i = 0;
  for (int y = 0; y < MAX_Y; y++) {
    int a = font[i++];
    for (int x = 0; x < MAX_X; x++) {

      if (((a << x) & 0x80) != 0) {
        Pixel[y][x][0] = c1;
        Pixel[y][x][1] = c2;
        Pixel[y][x][2] = c3;
      } else {
        Pixel[y][x][0] = 0;
        Pixel[y][x][1] = 0;
        Pixel[y][x][2] = 0;
      }  //if

    }  //for j
  }    //for i

  NeoPixe_OUT();  //RBG LEDに出力

}  //ch_8x8


//初期化
void setup() {

  //ネオピクセルの設定
  strip.begin();
  strip.show();

  //kanji_scroll_clr();

  //シリアルポートの設定
  //Serial.begin(9600);
  //Serial.println();
  //for (int i = 0; i < 9; i++) {
  //  Serial.print('.');
  //  delay(500);  //接続待ち
  //}              //for
  //Serial.println();

}  //main


//メインループ
void loop() {

  unsigned char font[8];  // フォント格納バッファ

  char *str = "あ、埼玉";  // 文字列
  char *ptr = str;

  kanji_scroll_clr();

  while (*ptr) {  // 文字列分ループ

    ptr = getFontData(font, ptr);  // 1文字分のフォント取得
    if (!ptr)
      break;  // エラーの場合は終了

    kanji_scroll_set(font);

    for (int i = 0; i < 8; i++) {

      kanji_scroll_1up(font);
      //font_data_out(font);

      ch_8x8_f(font, 5, 5, 5);
      delay(500);  //0.5秒待つ

    }  //for

  }  //while

}  //loop


```
毎日write up 3日目 jAuth

# 問題
### Description
Most web application developers use third party components without testing their security. Some of the past affected companies are:
Equifax (a US credit bureau organization) - breach due to unpatched Apache Struts web framework CVE-2017-5638
Mossack Fonesca (Panama Papers law firm) breach - unpatched version of Drupal CMS used
VerticalScope (internet media company) - outdated version of vBulletin forum software used
Can you identify the components and exploit the vulnerable one?
Additional details will be available after launching your challenge instance.

サードパーティ制のコンポーネントには脆弱性がある場合があるから気をつけようね的なことが書いてあります。何かしらライブラリ等の脆弱性をつくのでしょうか
![スクリーンショット 2025-05-08 20.57.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/64272986-f022-45bb-be3d-029a231374dd.png)



## 解答
早速書いてあるtestとTest123!でログインしてみます
![スクリーンショット 2025-05-08 21.51.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/797d7ccd-e19a-4979-a451-7996c1ad0f19.png)

ログアウトボタンがあるのみで、特になにもないです。

いつものごとくプロキシツール等で通信をみると、/authでのPOSTでレスポンスとしてSet-Cookie:token=にトークンが帰ってきています。/privateのリクエストをみてもこれが使われていることがわかります。

以下のサイトでデコードしてみます

https://jwt.io/

![スクリーンショット 2025-05-08 22.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/319e8f7b-834b-46a6-a9e8-8d5f4d67dce3.png)

"role": "user"をadminに書き換えることができたら良さそうですが、署名されているためこのままでは書き換えることができません。

サーバー側のスクリプトもなければ鍵もなく、署名アルゴリズムも比較的安全なので正面突破は難しそうです

しかし他に怪しいところもないので、脆弱性やテクニックを探します。

するとjwtにアルゴリズムをnoneにする攻撃があることを発見

https://qiita.com/ockeghem/items/cc0b8ab74f46834d055b

まさしくこれですね。algをnoneに書き換えます。
これでHSAの署名を掻い潜り、好き勝手にjwtトークンを書き換えることができます。
先程のサイトでデコードからエンコードに切り替えて、algとroleを書き換えてエンコードします。
![スクリーンショット 2025-05-08 22.41.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853234/c9b1dceb-8970-42a7-881b-df25f2c6faae.png)
そして得られたトークンを使ってcurlやプロキシツールをつかってリクエストを送るとflagを入手できました
【AWS】エラー「type of argument max_allocated_storage must be one of (int, float, NoneType); got str instead」の原因

# 概要
AWS CDKでRDSインスタンスを作成して`cdk deploy`すると以下のエラーに。

> TypeError: type of argument max_allocated_storage must be one of (int, float, NoneType); got str instead

原因と解決方法を紹介します。

# 原因と解決方法
エラーの原因は、`max_allocated_storage`に渡している値が文字列 (str) 型であるためでした。
メッセージにある通り、プロパティは数値 (`int`または`float`) 型にする必要があります。

以下のように変更すると、エラーが出なくなりました。

```py
       rds_instance = rds.CfnDBInstance(
            self, "Sample-RDS",
            db_instance_identifier="sample-mysql8",
            db_instance_class="db.t3.micro",
            db_name=db_name,
            engine="mysql",
            engine_version="8.0.41",
            allocated_storage="20",
            max_allocated_storage=100, # intに変更
            db_subnet_group_name=rds_subnet_group.ref,
            vpc_security_groups=[rds_security_group.security_group_id],
            master_username=rds_secret.secret_value_from_json("username").unsafe_unwrap(),
            master_user_password=rds_secret.secret_value_from_json("password").unsafe_unwrap(),
            publicly_accessible=False,
        )
```

あれ、でも、`allocated_storage`は`int`型にしなくても良いのはなぜだろう？と思い、AWS公式ドキュメントのCloudFormationのRDSリソース仕様を確認してみました。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbinstance.html

すると、

> AllocatedStorage: String

> MaxAllocatedStorage: Integer

とあります。

`AllocatedStorage`と`MaxAllocatedStorage`で期待している型が違う！？
これは知らなかった...

ということで、以上！
ChatGPTの会話ログを一括でマークダウンの構造化データにしてobsidianに投入

掲題の通りのことをしたのでやり方の記録を残します。

# 背景
- 個人の構造化データを楽に取得する仕組み化が次のトレンドな気がした
   - 会社特化の小規模なLLM、RAGを簡単に構築できるサービスが今流行っている
   - 個人特化のもっと小規模なLLM、RAGを作るのが次のトレンドな気がする
   - 小規模なLLM、RAGを作るのに必要なのは構造化データの収集
   - chatgptの会話ログを取得して構造化データにするのがよさそうに思えた

# 環境
- windows 11
- Obsidianインストール済

# 手順
## Chatgptの会話ログをjson形式で取得
- ![export.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079551/dcec069a-2d93-4d7a-9c61-045de87136ca.png)

- WEBサービスの右上のユーザアイコンから設定→データコントロール→エクスポートする
- Open AIからダウンロードリンクつきメールが届く

##![folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079551/551d71fe-182e-4a1a-9263-090d9ccc8105.png)

- ダウンロードしたファイルを解凍すると conversations.json という会話のjson形式ログが取得できる

- なお、ブラウザの拡張機能"ChatGPT Exporter"で最初からマークダウン形式でファイル取得できるけど、過去分すべて一括でexportができない

## マークダウン変換、ついでにメタデータ付与
- 自前の変換ツールつかいます。Githubにマークダウン変換するプロジェクト自体は既にあったのですが、最新の形式に対応していなかった？のと、ライセンスが書いてなくてforkしていいか聞くのが面倒でした
https://github.com/shirousuda/chatgpt_json2md/tree/main/releases
- ここからjson2md.exeを取得して、conversations.json と同じディレクトリに配置して実行してください
- 実行バイナリファイルはwindows用のしかつくっていませんので、他の環境ならソースコードからの実行になります
- 構造化データがほしいというところで、初期設定だとログにないメタ情報を色々勝手に付与します。設定で無効にできます

## RAGをつくるまでは頑張れないのでObsidianに入れる
![plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079551/d5161a65-7d4f-4646-b871-07675ceeb5fc.png)

- smart connectionプラグインをインストール。ホーム画面左下の設定アイコンを押下、設定画面左メニューよりコミュニティプラグインを選択、コミュニティプラグイン項目よりコミュニティプラグインを押下、検索画面でsmart connectionを検索
![scsettei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079551/d289618a-38a7-4e7c-8c6b-76f032973acd.png)
- smart connection設定画面よりshow full path を有効化

![ret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079551/24408eca-00dd-4358-abb2-162566ec313f.png)
- しばらくsmart connectionの読み取り後、適当なノートを開いてから、smart connectionの画面を開くと、関連する記事一覧がでてくる。なんでアンパンマンの記事に対してアロエ..？


# 感想
- 使う生成AIを選ぶにあたって、会話ログをとれるサービスかどうかもポイントになってくる気がしました。Chatgptはログを保存してくれて、構造化データとして出力してくれてえらい。Copilotだとログを保持しないので、随時ログ保存みたいなことする必要ありそうです
- 構造化データを作る観点で、Chatgptと会話するとき、トピックが切り替わったら新しい会話に移行したほうがいいと思いました。添付のアンパンマンの記事だと、同じ会話の下のほうで、夜のお店にいくのは正当な離婚の理由になるかみたいなことを聞いているため、変なタグがついてます
PM2が自動再起動しないとき

再起動後にPM2が\*\*落ちる（プロセスが起動しない）\*\*原因は、以下のいずれかが多いです：
### 再起動のタイミングが悪いとｐｍ2のパスが切れることがあるこれはその復旧方法とその対策である

---

### 🧠 よくある原因と対策

#### ✅ 1. **PM2が自動復旧設定されていない**

PM2は「再起動後に自動で復元する」設定をしておかないと、再起動後にプロセスが立ち上がりません。

**対策**（一度だけ実行すればOK）:

```bash
pm2 startup
```

このコマンドを実行すると、最後に表示される `sudo` コマンドをコピーして実行してください。

そして：

```bash
pm2 save
```

> **これで今のプロセスが再起動後にも自動で復元されます。**

---

#### ✅ 2. **PM2自体が再起動時に起動していない**

`systemd` などの仕組みがPM2を起動していない場合です。

**チェック方法**:

```bash
which pm2
```

または、

```bash
pm2 ls
```

→ 「Command not found」になる場合は `~/.nvm` や `~/.npm` のPATHが通っていない。

**対策**：

```bash
export PATH=$PATH:/home/ユーザー名/.nvm/versions/node/xxx/bin
```

または `.bashrc` / `.zshrc` に追記。

---

#### ✅ 3. **`pm2 save` をしていない**

再起動後に「プロセスがゼロ」になる場合は、`pm2 save` をしていなかった可能性が高いです。

---

### 🛠️ 解決手順（1回設定すればOK）

```bash
pm2 startup
# ↑ 最後に表示される「sudo ...」を実行

pm2 save
```

そして再起動して確認：

```bash
sudo reboot
```

再起動後：

```bash
pm2 ls
```

---
KSNCTF #7 Programming

# Programming
https://ksnctf.sweetduet.info/problem/7

## C++コード

```c++
#include   	 	<stdio.h>    
	
     	#include  	  <string.h>	
	
  int   	  	main		 
	()
   {   	const		char 	* 
s	=
 "     	    " 
"0123456789"	
"     "
	
"		   "
"			         							  				 			 "    	  
	 "ABCDEFGHIJ" 	;
	 printf	(
   	  "%c"	,		strlen 
(s)	
 );  int  i	  =	020000000	+	001000000	+
000600000	
  +000040000
+000007000
+000000500
+000000020
+000000002  	;
   	  	printf		(	
	"%s"
     	,&  	 i		
	)
;        	 	 
	long
    long 
			   							  				 		 	 					 l
	  =	 
 	
  2LL   		 
	    *
 	11LL
     	 		
	  	 *
 	229LL
     		 
	    *
 	614741LL
     		   
	    *
 	9576751LL
     		 	 
	  	 +
 	5LL
     	 	   
	    
 	;
     		  	
	  	 
 	printf
     	  	  (
	  "%s"  
 	
     	    ,	 
	  	 
 	
    & 	    
	    
 	
     		l	 
	    
 	
    ) 			 
	    
 	
     		 		;
	  	 
 	
    float 	 	
	    
 	
     	f		 =	
	    
 	
     1.0962664770776731080774868826855754386638240000e-38f	  
	  	 
 	
     ;	  
	    
 	
     printf(		"%s"	  
	  	 
 	
     	 ,		 
	    &f
 )	
    ; 	   	 
	double  	 
 	
d     		 			=
	6.7386412564254706622868098890859398199406890000e-308  	 
 ;	
  printf
("%s"
,&d);
}
```
わけのわからないインデントで書かれたc++コードが配布されています。

とりあえずきれいにしてみる

```c++
#include <stdio.h>
#include <string.h>

int main()
{
	const char *s =
			"     	    "
			"0123456789"
			"     "
			"		   "
			"			         							  				 			 "
			"ABCDEFGHIJ";
	printf("%c", strlen(s));

	int i = 020000000 + 001000000 +
			000600000 + 000040000 + 000007000 + 000000500 + 000000020 + 000000002;
	printf("%s", &i);

	long long l =2LL * 11LL * 229LL * 614741LL * 9576751LL + 5LL;
	printf("%s",&l);

	float f =1.0962664770776731080774868826855754386638240000e-38f;
	printf("%s",&f);
	
	double d = 6.7386412564254706622868098890859398199406890000e-308;
	printf("%s", &d);
}
```

実行結果は`FROG_This_is_wrong_:(`

これは違うらしい。

## whitespace?
whitespaceというプログラミング言語があるみたいです。
知らなかったので、これは解けませんでした。

https://vii5ard.github.io/whitespace/

---
そのままコピペして実行しました
![スクリーンショット 2025-05-08 105236.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4055936/35d0f977-06bf-4661-aa6a-d8fbc51df1e8.png)

PINが必要らしいです。
Debugに文字コードぽいのが並んでいるので、見てみます。

```
push 80 -->P
printc
push 73 -->I
printc
push 78 -->N
printc
push 58 -->:
printc
push 32 -->空白
printc
push 0
readi
push 0
retrieve
push 33355524
sub
jz label_0
push 78 -->N
printc
push 79 -->O
printc
end
label_0:
push 79 -->O
printc
push 75 -->K
printc
push 10 -->改行
printc
push 0
retrieve
push 33355454
sub
dup
printc
push 6
add

```

PINを入力して、OKかNOの判定があるらしいですが、適当な入力をしても返答がないです。
おそらく33355524と33355454のどちらかがPINになってるのかなと思います。
Cursorを使ってみたかったので手始めに簡単なテキスト処理をやってみた

# Cursorを使ってみた：簡単なテキスト処理の実践記録

## はじめに

最近話題のエディタ「Cursor」+ Vibe coding が気になっていて、環境構築とか難しそうでちょっと躊躇していたのですが、まずは簡単なテキスト処理から始めてみることにしました。

流行りのAIツールを使わない手はないですよね。

## 今回の目的

- Cursorの基本的な使い方を体験してみる
- 昔書いた記事を再編成してみる
- Qiitaに記事を公開してみる

## 実施した作業

### 1. 準備
- Cursorをインストール
- 昔書いた記事（HTML形式）を新規ディレクトリにコピー

### 2. 作業手順
1. Cursorに記事の再編成をお願いしてみる
2. 生成された内容を確認
3. 必要に応じて手動で調整
4. Qiitaに公開

実際の作業の様子がこちら。

Cursorに指示を出す際の画面です：

![Cursorでの指示画面1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3578004/bfb19c71-4c1a-40c0-b75c-5a05f7027511.png)


Cursorが応答して、記事の再構成を提案してくれました：

![Cursorでの指示画面2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3578004/6389f628-9f6e-43aa-8019-7fecb6401176.png)


### 3. 結果
記事の再編成が完了して、無事にQiitaに公開できました！
公開記事: [記事のリンク](https://qiita.com/oct0pus8winner/items/3efd4b3a3041ffdbe3d1)

## 感想

Cursorを使ってみた（と言っていいのかと思うほど少ない作業量ですが）感想

- 直感的な操作で簡単にテキスト処理ができた
- すぐに試せた

実際のチャットログを見ると、Cursorはこんな感じで作業を進めてくれました：

1. リポジトリの内容を確認
2. HTMLファイルの内容を分析
3. Qiita用の記事構成を提案
4. マークダウン形式での記事作成
5. 投稿手順の詳細な説明

このように、Cursorは単なるテキスト処理だけでなく、コンテキストを理解した上で適切な提案をしてくれるのが面白いなと思いました。

## 今後の展望

今回の経験を踏まえて、次のようなコンテンツに触ってみたいななんて考えています：

- もっと複雑なテキスト処理に挑戦してみたい
- MCPとか、気になってるけどまだ使えてない機能を試してみる
- 他の開発タスクでも使ってみたい

## まとめ

Cursorは、AIの力を借りながら効率的に開発作業を進められる便利なツールだなと感じました。
これからもCursorを活用して、より効率的な開発作業を目指していきたいと思います！

...というのもほとんどcursorで書いてもらいました（）
関数型プログラミングの「関数を引数にする」という事


タイトル詐欺でごめんなさい。
これから解説する事象はPowerQueryなので、Haskellや本格言語には当てはまらないかもしれませんが、本質的、根本的には同じだと思います（抽象化）。

    結論 = Excelは最強のノーコード、ローコードツールだった(ファンクション関数)

以下解説


    let
    ソース = Excel.CurrentWorkbook(){[Name="ソース"]}[Content],
    //初手Table.Bufferしていますが、これはあくまで解説用
    元 = Table.Buffer(Table.TransformColumnTypes(ソース,{{"文字列", type text}})),
    リスト用テーブル = Excel.CurrentWorkbook(){[Name="リスト用テーブル"]}[Content],
    リスト = List.Buffer(List.Distinct(リスト用テーブル[リスト用列])),
    
    //ファンクション関数を宣言（今回の例では　列追加　という名前のファンクション関数です）
    //引き渡す引数はList.Accumulate関数で引き渡された引数を使用
    
    列追加 = (列を追加したテーブル, 現在値の項目) =>
    let
    //リスト用テーブルの条件リスト列をリストの現在の値(カレント)でフィルターし、リスト用テーブルの[条件リスト]列を戻り値にする（答え、演算結果）、代入する
    条件リスト = Table.SelectRows(リスト用テーブル, each [条件リスト列] = 現在値)[条件リスト列],
    
    //上で条件リスト変数（ステップ名）に代入した「条件リスト」を活用、利用し、下のTable.AddColumn関数から引き渡した列を追加したテーブルの[文字列]列に「条件リスト」の値、項目が含まれていないか調べる
    //つまりOR OR OR...条件
    
    フィルタ = (文字列) =>  List.Select(条件リスト, each Text.Contains(文字列,_)),
    //上の関数で返された結果を（今回の例では）スペース区切りで結合（List.Select関数は条件に合致したリストをプレゼントしてくれます）
    
    合致した項目を結合 = (x) => Text.Combine(x," "),
    
    //やっと本題です、お伝えしたかったことは既存の関数でネスト出来る事は、ファンクション関数、カスタム関数でもネスト出来ますよ、という事です。　
    処理結果 = Table.AddColumn(列を追加したテーブル, 現在値の項目,each 結合(フィルタ([文字列])))

    in 
    処理結果,
                                                    //列追加　はファンクション関数
    列を列名リストにもとづいて動的に追加 = List.Accumulate(リスト,元,列追加)

    in
    列を列名リストにもとづいて動的に追加

どうでしょうか？
普通に書けば

    List.Accumulate(List,TableName,(累計値,current) => Table.AddColumn(累計値,current,each Text.Combine(List.Select(Table.SelectRows(リスト用テーブル,(x) => [条件リスト] = current)[条件リスト],(y) => Text.Contains([文字列],y)," "))

という非常に長い関数のネストを一筆書きで書かなければなりません。
しかし、カスタム関数によって、
それぞれの処理が、
一行ずつ記述する事が出来、最終的に

    結合(フィルタ([文字列]))

と書くことが出来ます

フィルタ関数で条件に合致した項目が返され,
その結果のリストが、
そのまま結合関数(リスト)の引数として引き渡される、
ということですね

これは二階建だそうです

オチ

    これってワークシート関数のネストじゃないか！

以上
Githubを設定振り返り用ログ

# Githubを設定した話

## はじめに

この記事では、WSL2とVSCodeを使用してGitHub Pagesを設定し、運用する方法について解説します。Windows PCを新しくセットアップする機会に、GitHubの設定から運用までを一通り実践してみました。その過程で得た知見を共有させていただきます。


:::note warn
この記事は、2023年に公開したページを再編集したものです。
情報が古くなっている可能性がありますので、ご了承ください。
:::

## 対象読者

- WSL2 × VSCode × GitHub を使い始めたい人
- GitHubにSSHで接続したい人
- GitHubに公開してあるリポジトリをクローン・編集したい人

## 環境構築

### WSL2の設定

WSL2のインストールと初期設定は完了していることを前提とします。
まだの方は、[Microsoft公式ドキュメント](https://learn.microsoft.com/ja-jp/windows/wsl/install)を参照してください。

### VSCodeの設定

1. VSCodeをインストール
2. WSL拡張機能をインストール
3. GitHub拡張機能をインストール（最新のVSCodeには標準で含まれている場合があります）

## GitHubとの連携

### SSH鍵の生成と設定

まず、GitHubのリポジトリにアクセスするためにSSH鍵を生成します。

```bash
# SSH鍵を保存するディレクトリを作成
mkdir ~/.ssh
cd ~/.ssh

# RSA鍵を生成
ssh-keygen -t rsa
```

鍵の生成時に3回の入力を求められます：
1. 鍵の保存場所（デフォルトでOK）
2. パスフレーズ（セキュリティのため設定推奨）
3. パスフレーズの確認

生成した公開鍵をGitHubに登録します：

```bash
# Windowsの場合
clip.exe < ~/.ssh/id_rsa.pub

# Macの場合
cat ~/.ssh/id_rsa.pub | pbcopy
```

GitHubの設定手順：
1. GitHubにログイン
2. Settings > SSH and GPG keys
3. "New SSH key"をクリック
4. Titleに識別しやすい名前を入力
5. Keyにコピーした公開鍵を貼り付け
6. "Add SSH key"をクリック

接続テスト：

```bash
ssh -T git@github.com
```

成功すると以下のようなメッセージが表示されます：
```
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
```

### GitHubアカウントの設定

Gitの初期設定を行います：

```bash
git config --global user.email "your.email@example.com"
git config --global user.name "Your Name"
```

## リポジトリの操作

### リポジトリのクローン

1. GitHubで対象のリポジトリを開く
2. "Code"ボタンをクリック
3. "SSH"タブを選択
4. 表示されるURLをコピー

```bash
# リポジトリをクローン
git clone <コピーしたURL>
```

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

ファイルを編集した後、以下の手順で変更を反映します：

```bash
# 変更したファイルをステージング
git add <ファイル名>

# 変更をコミット
git commit -m "コミットメッセージ"

# 変更をプッシュ
git push -u origin main
```

`-u origin main`オプションを使用することで、次回からは単に`git push`で更新できます。

## VSCodeでのGitHub操作

VSCodeのGUIを使用してGitHubの操作を行う方法：

1. 左側のSource Controlアイコン（分岐マーク）をクリック
2. 変更したファイルが表示される
3. "+"ボタンでステージング
4. コミットメッセージを入力
5. "Commit & Push"ボタンで一括操作

## まとめ

この記事では、WSL2とVSCodeを使用したGitHub Pagesの設定から運用までの基本的な手順を解説しました。特に以下の点に注意して設定を行うことで、スムーズな開発環境を構築できます：

- SSH鍵の適切な生成と管理
- Gitの初期設定
- VSCodeの拡張機能の活用

これらの設定を行うことで、安全かつ効率的なGitHub Pagesの運用が可能になります。

## 参考リンク

- [GitHub公式ドキュメント](https://docs.github.com/ja)
- [WSL2公式ドキュメント](https://learn.microsoft.com/ja-jp/windows/wsl/)
- [VSCode公式ドキュメント](https://code.visualstudio.com/docs)
エラーメッセージを信用しない

## 最初の仮説としては信用する

たとえば `E40101: 認証に失敗しました。ログイン情報をご確認ください。` というエラーメッセージが表示された場合、最初に入力データを疑うのはOK。しかし入力データに固執すべきではない。

内部でどのような処理が実行されたかに着目が大切。
信頼性の高い処理や、本番同等の環境で問題が発生していないといった明確な根拠がある場合は別だが、開発中の機能などでは、そのような前提は成立しないことが多い。

## エラーメッセージから立てられる仮説

この時点で確実に言えるのは、「`E40101: 認証に失敗しました。ログイン情報をご確認ください。` というメッセージを表示する処理が実行された」という一点だけ。

## 原則

原則として、中身の動きを前から順を追っていくと原因がわかる。

今回の例であれば、DB接続プールの上限に達した結果、認証APIが 503 を返していたにもかかわらず、適切なエラーハンドリングがなされておらず、結果として誤って上記のエラーメッセージが表示された、というケースもある。

こういった場合も中身の動きを前から順に追っていくと原因確認可能。
swift-idを使ってデータクラスの固有型でIDを定義する

# swift-idを使ってデータクラスの固有型でIDを定義する

- `Identifiable`に準拠したデータクラスはIDを持ちますが、例えばこのIDの型をStringすると、複数のデータクラスがあった際にIDを混同して使ってしまう懸念があります
- そこでIDをデータクラス固有の型にしたいことがあり、その際は[koher/swift-id](https://github.com/koher/swift-id)のライブラリを使うのが便利です
- ライブラリのREADMEの通りIDを定義して利用できます

```swift
struct User: Identifiable, Sendable, Hashable, Codable {
    let id: ID
    var name: String

    // 🙂 Easy to implement!!
    struct ID: StringIDProtocol {
        let rawValue: String
        init(rawValue: String) {
            self.rawValue = rawValue
        }
    }
}
```

- ここでデータクラスが多い場合に毎回ID型を定義するのが手間なので、下記のようにジェネリクスを使って汎用型を定義すると便利です

```Swift
import SwiftID

// クラス固有のIDを定義するための汎用型
public struct SwiftID<T>: StringIDProtocol {
    public let rawValue: String
    public init(rawValue: String) {
        self.rawValue = rawValue
    }
}

/// GitHubAPIで扱うDTOクラス用のプロトコル(こちらは一例で必須ではないです)
public protocol GitHubItem: Identifiable, Codable, Sendable, Hashable, Equatable {
    associatedtype T
    var id: SwiftID<T> { get } // 各クラスにユニークな型のIDを定義させる
}
```

- 利用例としては以下の通りです

```swift
public struct MyRepo: GitHubItem {
    
    // MARK: - 検索結果から取得される値
    
    private enum CodingKeys: String, CodingKey {
        case rawID = "id"
        case name
        case owner
        case starsCount = "stargazers_count"
    }
    
    public let rawID: Int
    public var name: String  // e.g. "Tetris"
    public var owner: User
    public var starsCount: Int
    
    // MARK: - Identifiable
    
    /// 固有型のID
    public var id: SwiftID<Self> { "\(rawID)" }
}
```
テックブログを1ヶ月続けて得られたこと・改善点

## はじめに

ちょうど1ヶ月間、毎日テックブログを書き続けてみました。
このタイミングで、良かった点や改善したい点などを整理しておこうと思います。

## 良かったこと

毎日最低1つは「気になったこと」「疑問に思ったこと」を深掘りする習慣ができたことが、1番の収穫でした。
開発を一切しない日でも、必ず何かしら知識を得ることができました。

習慣になってしまえば、むしろ書かないと気持ち悪くなるので、この感覚になれたのが大きかったです。

## 改善点

テックブログを始めたきっかけの一つは、転職活動のアピール材料にすることと、学んだ内容を深く理解することでした。

これからは、1日を振り返って
	•	何を学んだのか
	•	何ができるようになったのか
	•	何が理解できるようになったのか

を、日報のようなスタイルで書いていこうかと考えています。

あと、個人ブログを解説し、そこにテックブログを書き、誰かにシェアしたい内容は、QiitaやZennなどに投稿するのが良いかなと思い始めました。

## おわりに

テックブログを続けることで多くの学びがありましたが、やはり一番の恩恵は「習慣になったこと」でした。
この習慣をベースに、より学びの濃密度を上げていこうと思います。
【初学者】JS・Rails本日の学習内容

# JavaScriptとAPIの基本的な理解 🌐
本日は、JavaScriptやWebAPIに関する基本的な概念を学びました。まず、APIとは「アプリケーション・プログラム・インターフェース」の略で、異なるソフトウェア同士が通信するためのルールを定義したものです。WebAPIは、インターネットを介して外部サービスとデータをやり取りする手段として広く使用されており、特にサーバーとクライアント間のデータ交換に役立ちます。

## 1. XMLHttpRequestオブジェクトとsend()メソッド 📡
JavaScriptを使ってWebAPIと通信するために、XMLHttpRequestオブジェクトを使います。このオブジェクトを利用して、外部APIにデータをリクエストしたり、レスポンスを受け取ったりします。

### ・open()メソッド：
リクエストを初期化するために使います。HTTPメソッド（GET、POSTなど）やURL、非同期/同期設定を指定できます。

### ・send()メソッド：
リクエストをサーバーに送信します。

### 2. JSON形式でデータを扱う 📦
WebAPIでデータをやり取りする際、一般的にJSON（JavaScript Object Notation）フォーマットが使われます。これは軽量で扱いやすいデータフォーマットです。JSON形式で返ってきたレスポンスは、JavaScriptでオブジェクトとして扱うことができます。

### 3. イベント処理：onloadとpreventDefault() ⚙️
APIリクエストの結果を扱う際には、onloadプロパティを使用して、リクエストが成功した場合に処理を実行します。また、フォーム送信などでページリロードを防ぐために、preventDefault()メソッドを使います。これにより、非同期的に処理を行うことができます。

# RailsとAPIに関する理解 💻
Railsの開発では、サーバーサイドとフロントエンドを分離して、より効率的に開発を進めることができます。このアーキテクチャでは、フロントエンドはJavaScriptで構築し、サーバーはAPIを提供します。

### 1. RailsのAPIオプション 🛠️
Railsでは、rails newコマンドを使用してAPI専用のアプリケーションを簡単に作成することができます。このオプションを使うと、デフォルトでビュー関連のファイルが省略され、純粋にAPIとして機能するバックエンドが作成されます。

### 2. サーバーとフロントエンドの分離 🔗
サーバーサイドとフロントエンドを分けることにより、より柔軟な開発が可能になります。これにより、例えばReactやVue.jsといったフレームワークを使って、フロントエンド部分を独立して開発できます。分離のメリットとしては、スケーラビリティやメンテナンスのしやすさが挙げられます。

## 開発ツールとデプロイメントについて ⚙️
### 1. デプロイとサービス公開 🌍
アプリケーションが完成したら、実際に公開する作業（デプロイ）が必要です。デプロイには、HerokuやAWSなどのクラウドサービスを使う方法が一般的です。また、公開する際には、Basic認証を設定して、セキュアなアクセス管理を行うことも大切です。

### 2. シェル、Zsh、vimの基本操作 💻
シェル: コマンドラインインターフェース（CLI）を使うことで、サーバーやローカル環境の操作が効率的に行えます。

### Zsh:
Zshは、Bashの代わりに使えるシェルの一種で、補完機能やエイリアスなどが便利です。

### vim:
高度なテキストエディタであるvimを使うと、コード編集が効率的に行えます。最初は難しく感じるかもしれませんが、慣れると非常に強力なツールです。

## まとめ
このように、WebAPIを使った非同期通信やRailsのAPIアプリケーション、シェルでの作業などを学びました。これから実際にコードを書いて、これらの知識をさらに深めていきたいと思います！
订单头（EKKO）的伝票日付（BEDAT）和登録日（AEDAT）有什么区别

✅ EKKO-BEDAT vs EKKO-AEDAT 的区别

| 字段名     | 中文名称               | 含义与作用                                                            |
| ------- | ------------------ | ---------------------------------------------------------------- |
| `BEDAT` | **采购凭证日期**（订单日期）   | 指**业务上定义的采购订单日期**。通常是用户在创建采购订单时在界面上输入的日期，可以与系统日期不同。用于打印、对账、合同控制等 |
| `AEDAT` | **创建日期**（系统记录的创建日） | 指这笔采购订单在**SAP系统中被创建的实际日期**（系统自动填充），通常用于审计或流程追踪                   |


🧾 举个例子：
你在 2024/05/01 打开 SAP 创建采购订单，但你把订单日期设为 2024/04/30（因为要追溯昨天的需求），那么：

BEDAT = 2024/04/30（你自己输入的业务日期）

AEDAT = 2024/05/01（SAP 系统记录你今天创建的）
Manjaroでターミナルアプリが起動しなくなってしまった

Manjaro Linuxでターミナルアプリが起動しなくなってしまった。
一応、解決したのでメモ。

# 結論

https://forum.manjaro.org/t/error-while-loading-shared-libraries-libicuuc-so-75-cannot-open-shared-object-file-no-such-file-or-directory/175137/8

`gnome-terminal-fedora` というパッケージがいつの間にか Orphaned になっており、`vte` というパッケージのバージョンにミスマッチが起こっていたようです。

# 前提

2025年5月初旬に不具合を確認しました。

起動できなかったターミナル：

- gnome-terminal
- terminator
- lxterminal

起動できたターミナル：

- VSCode のターミナル
- Qterminal

なお、ファイルブラウザやインターネットブラウザなどは正常に起動できました。

# 調査

答えだけ知りたい方は、次章まで飛ばしてください。

## 再起動

再ログイン、再起動を試してみましたが、解決しませんでした。

## パッケージ類のアップグレード

ひとまずパッケージ類のアップグレードを試みます。

GUI が使えなくなってしまったときの回避策として、仮想コンソールというものがあります。
仮想コンソールは `Ctrl` + `Alt` + `F2` などで接続できます。
ちなみに `Ctrl` + `Alt` + `F7` で普段の GUI に戻ることができます。

```bash
yay
```

パッケージのアップグレードは正常に完了しました。
残念ながら、ターミナルはまだ起動できません。

## CLIから起動してみる

CLIから起動を試みると、エラー内容がコンソールに表示されることがあります。

```bash
gnome-terminal
```

エラーが出ました。

```bash
error while loading shared libraries libicuuc.so.75 cannot open shared object file No such file or directory
```

解決済みの先人がいることを願って、エラーメッセージでググってみます。
……ありました！

https://forum.manjaro.org/t/error-while-loading-shared-libraries-libicuuc-so-75-cannot-open-shared-object-file-no-such-file-or-directory/175137/8

# 原因

ターミナル起動時に発生したエラーメッセージは `icu` に関するものでしたが、実際の原因は `icu` に依存する `vte` のバージョンミスマッチのようです。

ターミナルの背景を透過させたかったため、 `gnome-terminal` ではなく `gnome-terminal-fedora` というパッケージを使用していました。
`gnome-terminal-fedora` がいつの間にか Orphaned になっており、同時に AUR で導入されていた `vte3` のバージョンが古いまま残されてしまい、バージョンが上がった `icu` とバージョンがミスマッチしてしまったようです。

# 解決

`gnome-terminal-fedora` を削除し、 `vte` も標準リポジトリにある新しいバージョンのものに切り替えました。
AUR で導入されていた古い `vte` については、新しいバージョンのパッケージをインストールする際に衝突するため削除を要求されました。

```bash
yay -R gnome-terminal-fedora
yay -S gnome-terminal
yay -S vte3 vte-common
```

無事、起動するようになりました！

# 余談

`yay` 実行時、AUR で導入した `vte` のバージョンが、標準リポジトリのものよりも古くなってるよ、と表示がでていました。
先に気がつけばよかった。。

# 余談2

`gnome-terminal` では、ターミナルの背景が透過できません。
どうしても透過させたいので、若干の恐怖を感じつつ AUR から背景透過版のターミナルを導入します。

```bash
yay -S gnome-terminal-transparency
```
【イベントレポート】Kubernetes Wakaran Tokyo #4 #k8swakaran

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

今回は2025.05.08（水）に開催した**Kubernetes Wkaran Tokyo #4**に参加しましたので、アウトプットとしてイベントレポートを執筆しました。

初見の方でもサクッと読めるように平易な表現で執筆しておりますので、お気軽に読んでいただければ幸いです。

:::note info
誤字脱字、わかりづらい表現、認識相違などは極力なくすように心がけています。そのうえで、リアルタイムで執筆しておりますので、誤字脱字、わかりづらい表現、認識相違などがあるかもしれません。
:::

#### イベントページ

https://k8s-novice-jp.connpass.com/event/351876/

# 目次
- ハンズオン
    - GKS環境へのログイン方法
    - GitHub CodeSpaceでの作業
    - Gcloudコマンドの実装
    - Kubernetes操作
    - Work Identity設定
- トークセッション
- まとめ

## ハンズオン

#### ハンズオン教材

https://t.co/geHkwRInsU

### GKS環境へのログイン方法

:::note info
基本的に以下内容に沿って行えば問題なさそう
https://support.google.com/qwiklabs/?hl=ja#topic=9114857
:::

- 作業内容としてQwiklabsへ登録すれば問題ない

https://explore.qwiklabs.com/discovery

- ハンズオン用環境についてはシークレットウィンドウで開いておく
    - （個人的意見）実務でマニュアルを作るときは注意ですね

### GitHub CodeSpaceでの作業
- 最上部までスクロールしないとハンバーガーマークが出ない
    - （個人的意見）機能を知らないのでキャッチアップしないとなぁ
- CodeSpaces=GitHub版VS Codeのイメージ
    - （個人的意見）ハンズオンで使えそうですね～
- Code Spaces立ち上げまで約5分ほどかかる

### Gcloudコマンドの実装

https://cloud.google.com/sdk/gcloud?hl=ja

- 環境構築後はGcloudコマンドの初期化を行う必要がある
- 環境変数の確認についてはcatコマンドで対応可能
    - （個人的意見）実務でも使える知識ね

### リソース構築

今回はTerraformを用いてリソースを構築

https://cloud.google.com/docs/terraform?hl=ja

- リソース構築前に認証処理を行う必要がある
- リソースアクセスのためにVPCを利用する
    - （個人的意見）毎日利用していますね
    - （個人的意見）各クラウドサービスごとにVPCの違いをまとめたいわね

### Kubernetes操作

https://kubernetes.io/ja/docs/reference/kubectl/

- config設定については**less ~/.kube/config**で確認可能
- 実行する前に**kubectl cluster-info**で情報取得が必要
    - （個人的意見）コマンドを覚えないといけないですね
- 外部公開する方法として**Pod⇒Nodes⇒Service**の順で処理する
    - （個人的意見）LBを作成できるのはうれしいわね
    - （個人的意見）きちんと学べば開発者体験が向上しますね～
- Pull⇒Pushに関してもシンプルに操作可能
    - （個人的意見）自動化したいですね

### WorkLoad Identity設定

https://cloud.google.com/iam/docs/workload-identity-federation?hl=ja

- ざっくり言えば**コンテナ利用時にIAM認証機能を付与する**イメージ
    - （個人的意見）実務で使えそうな機能ですね
- やることとしてBucketに格納されているファイルをPodからアクセスできるかどうかチェック
- kubectl execコマンドを利用すればLinuxコマンドを実行できる
- kubectl get pod <pod名> -wを付けることで常時表示できる
    - （個人的意見）運用を考えると使える機能ですね
    - （個人的意見）Service Account設定も楽なので使いたいですね！

## GKSあれこれ

### 参考サイト

https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-compute-classes?hl=ja

https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming?hl=ja

- AutoPilot自体はPod管理のみでいいがスペックを考えないと予期せぬコスト増が
    - Nodeレベルのセキュリティ対策
        - 必要最小限の設定のみのためアタックサーフェス対策は講じている
    - Podレベルのセキュリティ対策
        - 一部Linuxコマンドは制限しているためカスタマイズするのであればStandardを利用
        - kube配下のconfig編集は許可できない
- スケール速度を向上させる場合
    - Autopilotを利用する場合どうしても速度が遅くなる
        - イメージスケーリングや事前スケールで対処可能
            - （個人的意見）Auto Scalingの対策と似ていますね
        - そのほかにもBalloon Podを活用するのも一つの手
            - ざっくりイメージとして、**場所取り**
            - （個人的意見）実務で使う場合、考えないとですね

## まとめ

今回のセッションでKubernetesを初めて触ってみましたが、サービス開発ですごく使える印象を持ちました。そのうえで、今回のセッションを通じてKubernetes入門したのでキャッチアップしながらブログ・個人サービスをアウトプットしていきたいと思います！！

最後まで記事を読んでいただきありがとうございました！！
技術ドリブンな組織でテスト担当者が目標設定を実務に落とし込み、顧客満足と自己成長を実現する方法

## はじめに：目標設定は計画性だけで決まるのか？

「目標設定は計画性の高さで決まる」と感じることは多いですが、これはあくまで私の感想です。  
実際には、計画性の高さは目標達成に不可欠な要素の一つですが、**目標そのものの質や実行力、そして環境との整合性がなければ成果には結びつきません。**  
このことを踏まえ、今回は技術ドリブンな会社方針のもと、テスト設計・実施者がどのように目標を具体化し、顧客を巻き込みながら成果を出していくかを深掘りします。

---

## 1. 目標設定と計画性の関係：計画性だけでは不十分な理由

### 計画性は目標達成の土台

計画性が高いと、目標達成のための具体的な行動計画やスケジュールが明確になり、効率的に進められます。  
しかし、計画性はあくまで「どうやって達成するか」の設計であり、**「何を達成すべきか」という目標の質が低ければ意味がありません。**

### 目標設定の質とは？

- **適切な目標の設定**：組織のビジョンや戦略に合致し、現実的かつ挑戦的であること
- **SMARTの法則**に沿った具体性と測定可能性
- **モチベーションを喚起し、関係者の理解を得られること**

これらが揃って初めて、計画性の高さが活きてきます。

---

## 2. 「視座を高く持て」と言われてもピンとこない理由とその最適化

### 視座の高さとは？

「視座を高く持つ」とは、単に目の前の業務だけでなく、会社全体の戦略や業界動向、顧客価値まで見据えた目標設定を指します。  
しかし、これを現場レベルの具体的な行動に落とし込むのは非常にエネルギーが必要で、多くの人が壁にぶつかります。

### ギャップを埋めるのがSMARTの法則

- **Specific（具体的）**：曖昧な目標を具体的に言語化する  
- **Measurable（測定可能）**：達成度を数値や指標で評価可能にする  
- **Achievable（達成可能）**：現実的な範囲で設定する  
- **Relevant（関連性）**：会社方針や顧客ニーズに合致させる  
- **Time-bound（期限付き）**：期限を明確にする

このフレームワークは、視座の高い抽象的な目標を、現場で実行可能な具体的な計画に変換するための「翻訳ツール」として機能します。

---

## 3. 技術ドリブン方針の中でテスト担当者が実務に落とし込む具体例

### 技術ドリブンとは？

会社が「技術ドリブン」を掲げる場合、技術革新や品質向上を軸に事業成長を目指します。  
テスト担当者はこの方針を理解し、以下のように実務に落とし込みます。

### 実務への具体的落とし込みポイント

- **技術方針の理解とテスト戦略の選定**  
  例：モデルベースドテストや自動化テストの導入など、新技術を活かした戦略を設計。  
- **早期関与と柔軟なテスト設計**  
  要件や仕様変更に素早く対応できるテストケースを設計し、開発サイクルの早期段階から関与。  
- **TDDやシフトレフトの推進**  
  開発プロセスにテスト駆動開発（TDD）やシフトレフトを組み込み、品質を上流で担保。  
- **定量的メトリクスでの管理と改善**  
  テストカバレッジ、バグ検出率、テスト自動化率などを定量化し、PDCAサイクルを回す。

---

## 4. 目標の定量化は難しい？TDD導入率30%の測定方法

### なぜ定量化が難しいのか？

TDDは「テストを書いてからコードを書く」という開発手法ですが、その実践度合いを数値化するのは簡単ではありません。  
単にテストコードの量やカバレッジだけでは、TDDの本質的な実践度を測りきれないからです。

### 定量化の具体的アプローチ

- **TDDサイクルの実施回数計測**  
  Red-Green-Refactorのサイクルを検出する専用ツール（例：Besouro）を利用し、実施割合を算出。  
- **コード・テスト比率の分析**  
  プロダクションコードに対するテストコードの比率を定期的にレビュー。  
- **テストカバレッジ・テスト密度のモニタリング**  
  変更箇所に対するテストカバレッジの推移を追い、TDD導入度合いを間接的に評価。  
- **セルフチェックやコードレビューによる運用評価**  
  チームでTDDの定義を明確化し、レビュー時に遵守度をチェック。

### 成果指標も重要

TDD導入率だけでなく、**バグ発生率の低下やフィードバックの早期化**など、成果に直結する指標も合わせて評価することが推奨されます。

---

## 5. 顧客を巻き込むことで目標達成と評価向上を両立する

### 顧客巻き込みの重要性

目標達成のために顧客を巻き込むことは、自身の活動の価値を最大化する鍵です。  
顧客のニーズや期待を直接理解し、目標と活動に反映させることで、顧客満足度と自身の評価が同時に高まります。

### 実践ポイント

- **目標の共有と合意形成**  
  顧客と自分の目標を明確に共有し、協力体制を築く。  
- **定期的なフィードバックループの確立**  
  顧客からの意見を受けて目標や計画を柔軟に調整。  
- **成果の見える化と報告**  
  進捗や成果を顧客に透明に伝え、信頼関係を強化。

---

## おわりに

技術ドリブンな組織で働くテスト担当者にとって、目標設定は単なる計画作成ではなく、**視座の高さと現場の具体性をつなぐ橋渡し**です。  
SMARTの法則や定量化ツールを活用し、顧客を巻き込むことで、目標達成の成功率を高め、顧客満足と自己成長を両立させましょう。  

---

**この記事が、目標設定に悩む現場の皆さんの参考になれば幸いです。**
素人が自作リバーシに強化学習AI乗っけてみた

## 制作の流れ

1. リバーシ(GUI)を作る

2. 評価関数式の(アルゴリズム的な)AIを作る

3. GUIを排除した、AI同士が何百試合もできるようなプログラムを作成する

4. 強化学習(Q学習)を実装する

5. 実際に学習させる

6. webで動かせるようにして投稿

### 1.リバーシ(GUI)を作る

 pygameを使い、リバーシのプログラムを作成します。

 強化学習についての話に重きを置きたいので細かいとこは省きますが、アルゴリズムの設計がちょっと難しかったですね。

 なんせ、ひっくり返す処理を考えたとき、ゲームボードの座標を選ぶので２次元、ひっくり返す方向を考えるので＋１次元、そこから何枚ひっくり返すかのカウントで＋１次元と、for文がすごいことになるので。

 とはいえ、探索そのものやひっくり返す処理自体は難しくなく、単にforネストが多いってだけですけど。

 <img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850890/641ce589-c5b9-4d4e-a93f-652ddcd5178f.png>

私が作ったのはこんなんです。ある程度のそれっぽさは欲しかったので多少UIを気にしたりしました。強化学習がしたいだけなら別に超無骨な画面ドーンでも問題はない。

 ### 2.評価関数式の(アルゴリズム的な)AIを作る

  これは強化学習に取り組む前に作ってみたかったというのもありますが、強化学習時の対戦相手としても必要になります。

  これには各マスの重み付けテーブルと、置いたときひっくり返せる数、そのほか若干の戦略を与えて、アルゴリズム的におく場所を決定するAIです。

  chatGPTとかと会話しながらコーディングすればわりとすんなりできました。

 ミニマックス法とか枝刈りはやってないです。実装大変そうだったので、強化学習に行き着くのを優先しました。

 ### 3.GUIを排除した、AI同士が何百試合もできるようなプログラムを作成する

  ようやく強化学習の手前まで来ましたね。まず、AI同士の対戦ではGUIなんていらないので、pygameを使って作ったリバーシプログラムから、pygame部分を全撤去してターン更新やひっくり返す処理など、アルゴリズム部分だけを残します。

  次に、もともとは最低片方のプレイヤーが人間だったと思いますが、これを評価関数対評価関数とか、ランダム手対評価関数みたいなのができるようにコードを改造します。

  ランダム手も強化学習には必要になるので、メソッドとしてまとめておきましょう。

  <img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850890/42b34609-190d-417b-a9ea-f99c83126a4d.png>

  イメージとしてこういうのができればよし。表示されてる数字は試合の決着時に自分の色がいくつだったかってやつです。

### 4.強化学習(Q学習)を実装する

ここでは強化学習の手法として、Q学習を使います。Q学習とは、簡単に言えば状態に対してどんな行動を取ったか、その行動にはどれだけの価値があったかということを表形式で記録することによって、経験的なものを積み重ねる学習方法です。

Q学習の実装は大きく分けると以下の通り。

- q_table(辞書)を定義する

- q_tableのセーブ・ロードを実装する(pickleを使えば瞬殺)

- Q学習時のパラメータを決める(後述)

- q_tableを参照して行動を決定する処理を作る

- 行った行動をもとにq_tableを更新する(=学習)

この辺は参考書とか買って勉強してもいいと思いますが、数学チックな話に興味がなければchatGPTに聞いたりネットでドキュメント漁ったりして実装できると思います。

一番難しいのがq_tableの更新です。更新式自体は公式に代入するだけなので楽ですが、ゲームやAIに少しでも馴染みがあれば聞いたことがあるであろう、強化学習時の報酬の与え方。これの調整がマジで難しい。これもやはりGPTを参考にするのが吉。

まあやってみるとわかるんですが、考え方は評価関数式のAIを作るときと似ています。良い戦略にプラス評価、悪い戦略にマイナス評価を与えるための条件と、条件ごとの報酬の増減を考えるって感じです。

### 5.実際に学習させる

4.で書いたQ学習のパラメータとは、学習率α、ランダム率ε、報酬の割引率γのことです。すべて0より大きく1より小さい範囲(0になったり1になったりはしない)で設定します。

素人なのでアレですが、肌感γは0.9以上で固定すればよさそう。
αとεは最初0.1くらいで、学習が進むごとにすこしずつ減少させていき、最後は0.01とかになる感じ。強いのを作るならともかく、それっぽいものを作るのが目的ならこんなふわっとしたイメージでもいける。

それぞれのパラメータの意味はGPTにでも聞いてください。多分、GPTに聞きながら自分のコードに落とし込んでいけばなんとなく想像がつく。

制作の中で最も苦戦したのがここでしたね。なにせ、今まで触ったことのあるジャンルと全く被らない分野のことやってるんで。パラメータをどれくらいの間隔でどれくらい減少させていくのかとか、ランダム手を相手に学習するのと、評価関数相手に学習するのをどのタイミングで切り替えるのかとか。

もっとしっかり学習させる場合は自己対戦をするらしいですが、元のリバーシプログラムの実装の仕方的にちょっと手間だったので、ここはスルー。

強いのが欲しいんじゃなくて、それっぽいのが欲しいんだ（言い訳）。

### 6.webで動かせるようにして投稿

これは単に私のアレがアレでアレですが、pygameなのでpygbagが使えます。pygbagの手順に従ってgithub pagesで公開しました。

https://at3388.github.io/MyReversi/

## さいごに
 
 強化学習でそれっぽいのができるとエンジニアしてる感があっていいですね。ただ一つ、言うことがあるとすれば。

 こいつchatGPT使いすぎだろ。
【クラウド】初学者　本日の学習まとめ

# 【クラウド】初学者　本日の学習まとめ
## クラウドとは？💡
今日はクラウドとその基本的な構成について学びました。クラウドとは、他社が所有するハードウェアやソフトウェアをインターネットを通じて利用できるシステムのことです。物理インフラ（サーバーやストレージなど）を仮想化して、ネットワーク経由でユーザーに提供しています。自分でサーバーを持たなくても、必要な分だけをクラウドサービスから借りて使えるというのが、クラウドの大きな特徴ですね。

## クラウドの基本構成
クラウドは大きく3つの層に分かれています。

### 1.インフラ層（Infrastructure Layer）
物理サーバーやストレージ、ネットワークなどの基盤部分です。これらは仮想化技術によって、クラウドプロバイダーが管理します。

### 2.プラットフォーム層（Middleware & OS Layer）
オペレーティングシステム（OS）やミドルウェア（データベースやサーバー管理ソフト）など、アプリケーションを動かすための環境が提供されます。

### 3.アプリケーション層（Application Layer）
最もユーザーに近い部分で、Webアプリやモバイルアプリ、クラウドストレージなどが提供されます。多くはSaaS（Software as a Service）として利用されます。

この3層構造を理解することで、クラウドの仕組みがより明確にわかります。特にAWS（Amazon Web Services）に関しては、EC2やS3、RDSなどのサービスを活用しながら、実際にインフラを利用する際に非常に役立ちます。

## クラウドコンピューティングの基本特性 🌐
次に、クラウドコンピューティングの5つの基本特性を学びました。これは、アメリカのNIST（国立標準技術研究所）が定義したクラウドの特徴です。

### 1.オンデマンドセルフサービス
必要なリソース（サーバーやストレージ）を、ユーザーが自分で即座に利用できるサービス。

### 2.広範なネットワークアクセス
インターネット経由でどこからでもアクセス可能。PCやモバイルから利用できます。

### 3.リソースのプール化
複数ユーザーが同じ物理リソースを共有して利用するため、効率的な管理が可能です。

### 4.迅速な弾力性
使用量に応じてリソースを増減でき、柔軟に対応できます。

### 5.測定されたサービス（従量課金制）
利用した分だけ課金され、リソースの使用量に応じて費用が発生します。

これらの特性を知っておくと、クラウドの利点や使い方がより理解しやすくなります。

## クラウドの3つのサービスモデル ☁️
クラウドサービスは提供する内容によって、以下の3種類に分類されます。

### 1.IaaS（Infrastructure as a Service）
仮想サーバーやストレージ、ネットワークなどの基盤となるインフラを提供するサービスです。AWSのEC2が代表例ですね。

### 2.PaaS（Platform as a Service）
アプリケーション開発に必要なOSやミドルウェアを提供してくれるサービスです。AWSのElastic Beanstalkがこれに当たります。

### 3.SaaS（Software as a Service）
完全なソフトウェアをクラウド上で利用できるサービスです。Google DriveやSalesforceなどがあります。

これらのサービスモデルを理解しておくことで、クラウド上で何を提供されているのか、どのモデルを使うべきかが見えてきます。

## クラウドの3つの提供形態 🏢
クラウドサービスは、提供形態によって以下の3つに分類されます。

### 1.パブリッククラウド
複数のユーザーが共有するクラウド環境です。代表的な例がAWS、Azure、Google Cloudなどです。

### 2.プライベートクラウド
特定の企業や組織向けに提供される専用クラウドです。セキュリティやカスタマイズ性が高いです。

### 3.ハイブリッドクラウド
パブリッククラウドとプライベートクラウドを組み合わせた形態です。AWSと自社データセンターを連携させる場合などがこれに当たります。

これらを理解することで、自分の目的に合ったクラウドサービスの選択ができるようになります。

## AWSの基本構成 🔧
WS（Amazon Web Services）は、クラウドサービスを提供するプラットフォームです。AWSの基本的な構成要素を学びました。

AWSは、主に以下の3つの層に分類されます。

### 1.インフラ層（IaaS）
代表的なサービスは、EC2（仮想サーバー）、S3（ストレージ）、VPC（ネットワーク）などです。

### 2.プラットフォーム層（PaaS）
RDS（データベース）、Elastic Beanstalk（アプリケーションホスティング）などがあります。

### 3.アプリケーション層（SaaS）
AWS Lambda（サーバーレスコンピューティング）、Amazon WorkSpaces（仮想デスクトップ）などがあります。

これらのサービスを利用して、インフラの構築からアプリケーション開発、管理まで、AWSでは一貫して行えます。

## 最後に
これからAWS資格の取得を目指して、もっと詳しく学んでいきたいと思っています。AWSのさまざまなサービスを学んで、どんなシステムやアプリケーションがクラウド上で動いているのか、理解を深めていきたいです！特に、どのサービスがどんな用途に使われるのかを理解することが、今後の学習のポイントだと感じています。

これからも引き続き学んでいきますが、質問やアドバイスがあれば、ぜひ教えてくださいね！
VBAで　配列の列をテーブルの列、シートの列　を列名などの文字で指定するあまりにも簡単な方法+おまけ


VBAはテーブルやシートを配列に取り込むと高速ですが、配列にアクセスするには数値しか使用できません（私の知る限りでは）
一方で、Excelのテーブルは、テーブル名と列名で列を指定することが出来ます。
なんとかテーブルやRange（範囲）を取り込んだ配列でも列名などの文字で場所を指定できないかと思い、考えました（数字よりも文字の方が他のお方が読んでも分かると思うので）。

レッツ　脱Range、Cells!

    Sub テスト()

    Dim 辞書 As Variant, ブック As Workbook, ファイルパス As String

    'ファイルパスは適せん指定、代入してください

    ファイルパス = ～

    Set ブック = 開く(ファイルパス)

    'Variantで宣言した理由は、arr = 辞書.Items　で辞書に登録した値そのものが代入出来るからです
    '好きに改変してください
    'オブジェクトは　必ず　Set (少なくともVBAでは、代わりにletは省略)
    Set 辞書 = 辞書に登録する(ブック)

    'あとは辞書("テーブル名列名")でテーブルの列のインデックスが指定できます

    '以下、解説、テスト用
    'bufってなんですか？
    Dim 項目 As Variant
    
    For Each 項目 In 辞書.keys
    
    Debug.Print 辞書(項目)
    
    Next 項目
    
    End Sub
    
    Function 開く(ByVal ファイルパス As String) As Workbook
    'これはおまけです。Workbook.Open(ReadOnly)が面倒な人向け&ファンクション関数とはなにか？解説用
    
    Set 開く = Workbooks.Open(ファイルパス)
    
    End Function
    
    Function 辞書に登録する(ByVal ブック As Workbook) As Object
    'メインテーマ
    '辞書を宣言
    Dim 辞書 As Object
    
    '辞書を早速代入
    Set 辞書 = CreateObject("Scripting.Dictionary")
    
    Dim シート As Worksheet, テーブル As ListObject, テーブルの列 As ListColumn, 辞書の項目 As String

    'ブックのすべてのシートをループ
    For Each シート In ブック.Sheets
        'シートの　すべてのテーブルをループ
        For Each テーブル In シート.ListObjects
            'テーブルのすべての列をループ
            For Each テーブルの列 In テーブル.ListColumns
            
                '辞書の項目、エントリー用変数（一般的な解説ではkey）
                'テーブル名と列名を使用して重複を回避、一意（ユニーク化）
                辞書の項目 = テーブル.Name & テーブルの列.Name
                '辞書に登録されていなければ（重複しなければ）
                If Not 辞書.Exists(辞書の項目) Then
                '辞書に登録、テーブルの列のインデックスを
                辞書.Add テーブル.Name & テーブルの列.Name, テーブルの列.Index
                
                End If
            
            Next テーブルの列
        
        Next テーブル
    
    Next シート
    '完成した辞書を引き渡す
    Set 辞書に登録する = 辞書
    
    End Function


Listobject.Listcolumn("列名").Indexでも指定できますが、
これはテーブルを一つ一つ代入しないといけないので非常に面倒くさいですね。
MacでAWSのCDK環境を構築

# 公式サイト
https://docs.aws.amazon.com/cdk/v2/guide/getting-started.html

# node.js ＆ npmのインストール
- ダウンロードURL
https://nodejs.org/en/

# node.js と npmのバージョン確認
```
% node --version
v22.15.0
% npm --version 
10.9.2
```


# AWS アカウントの準備
## 次のURLよりAWSのアカウントを作成（ある場合は、次のステップへ）
- URL
https://aws.amazon.com/jp/free/

## Identity and Access Management (IAM)でユーザーとユーザーグループ作成
※ユーザグループに「AdministratorAccess」ポリシーを追加

## アクセスキーを作成
ユースケース:コマンドラインインターフェイス (CLI)
アクセスキーと、シークレットキーをメモする

# Visual Studio Codeインストール
- ダウンロードURL
https://code.visualstudio.com/download

- mac版をダウンロードしてインストール

# AWS CLI v2をインストール
- ダウンロードURL
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html
- macOSをクリックして、[GUI installer]タブを選択し、次のmacOS pkgファイルをダウンロードして、インストールする
![スクリーンショット 2025-05-06 19.40.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079596/9880d433-451f-456f-859e-3b96be45b32d.png)
# AWS CLI のインストール確認
- ターミナルを起動して、「aws --version」コマンドを実行し、バージョンを確認
```
% aws --version
aws-cli/2.27.8 Python/3.13.2 Darwin/24.4.0 exe/x86_64
```

# AWS CLI のプロファイル作成
- ターミナルを起動して、「aws configure --profile $プロファイル名」コマンドを実行し、プロファイルを作成する

```
% aws configure --profile xxx
AWS Access Key ID [None]: AWSアカウントのアクセスキーを入力
AWS Secret Access Key [None]: AWSアカウントのシークレットキーを入力
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

# AWS CLI のプロファイル確認
- ターミナルを起動して、「aws sts get-caller-identity --profile $プロファイル名」コマンドを実行し、プロファイル及びアカウントIDを確認する
```
% aws sts get-caller-identity --profile xxx
{
    "UserId": "xxxxxxxxxx",
    "Account": "xxxxxx",
    "Arn": "arn:aws:iam::xxxx:user/xxx"
}
```

# CDKインストール
```
% sudo chown -R $userName /Users/$userName/.npm/_cacache
% npm install -g aws-cdk
```

※権限エラーが発生する場合、該当フォルダにユーザーからのアクセス権限を追加
Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules
```
% sudo chown -R $username /usr/local/lib/node_modules
```


# CDKバージョン確認
```
% cdk --version
2.1013.0 (build 054afef)
```

```
% mkdir hello-cdk && cd hello-cdk
% cdk init app --language typescript
```

# AWS アカウントに一回のみ実施
##ブートストラップを実施
```
$ cdk bootstrap  --profile xxx
```
Arduinoで強めのサーボモータを使う

https://qiita.com/hextomino/items/cd9ddd0931a7625cbea4

こちらの記事の続編です。

https://amzn.asia/d/cZSKp9T

このRDS3218を使います。
アーム付き。
トルクは約10倍。
価格は約８倍（アーム込み）。
4.8 ~ 6.8Vで動作。
2Aとあるので、USB電源だけでは、足りなそう。
※実際、サーボが動くと、Arduinoの書き込みができないので、書き込み時は、サーボを抜く必要がある。

| 型式 | トルク(KG) |角度|
|:-:|--:|:-:|
|SG90|約2|180|
|RDS3218|20|270|

# 組み立て
付属するアームがサーボと干渉しないように、ギアが中央にあるとき、垂直にアームを付けます。力でやると、かなり硬く、ギアが壊れそうなので、プログラムで中央にします。

```cpp:Arduino.ino
#include <Servo.h>

Servo myservo;

void setup() {
  myservo.attach(9);//９番使う
}

void loop() {
  myservo.write(90);//90度に設定
  delay(4000);
}
```

この状態で、アームを固定していきます。
ですが、アームの先をさらに固定するので、先に、固定先と接続したほうが良いです。


このサーボは270度回転するので、write命令の変数の意味が少し変わります。
write(90)で中央。
write(25)で、ほぼ-90度。
目分量で、関係式を導きます。
```
実際のサーボの角度 ＝ x*18/13-1620/13
```
write(0)とwrite(180)で目測250度しか回らない。

270度回すには、
```
myservo.attach(9,450,2450);
```
のように、設定する。デフォルトでは、
```
myservo.attach(9,544,2400);
```
らしい。これで、270度+α動かせる。


| write(x) | サーボ角度 |
|--:|--:|
|0|-135|
|30|-90|
|90|0|
|150|90|
|180|135|

```cpp
  myservo.write(25);//-90度に設定
```
```cpp
  myservo.write(155);//+90度に設定
```

# 可変抵抗で制御する

下記リンクのサーボコントローラでやるような、可変抵抗を操作してサーボを回すプログラム。

https://amzn.asia/d/2jh16wi

```cpp
#include <Servo.h>

Servo myservo;

void setup() {
  myservo.attach(9,450,2450);//９番使う
}

void loop() {
  int analog = analogRead(A0);
  int val = (int)((analog-512)/512.0*60+90);
  myservo.write(val);
}
```
0~1023でアナログ値を取得して、
30~150の範囲に変換する。
CMP(Compose Multiplatform)でデスクトップアプリを作ったらだいぶ楽だった話

最近デスクトップアプリを作りたいと思い、最初はWindowsだけでいいかとおもってUWPで作ろうと思っていたが、自分がAndroidエンジニアなこともあり、せっかくならCMPで作ってみようと思って作ったが意外とそんなに困ることがなく、OSにそこまで依存しないアプリならこれでもいいのではとなったお話


## 目次
- [DB周り](#db周り)
- [Paging周り](#paging周り)
- [File指定](#file指定)
- [Mouse操作](#mouse操作)

## DB周り
DesktopでもRoomを使うことが可能です。
具体的には、androidと違いContextを渡しますが、desktopではfileを渡します。

```kotlin
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
    val dbFile = File(System.getProperty("java.io.tmpdir"), "my_room.db")
    return Room.databaseBuilder<AppDatabase>(
        name = dbFile.absolutePath,
    )
}
```
これ以外の違いはあんまりなく、通常通り使えば使用できます。

## Paging周り
Pagingについては少々癖があります。
androidのpagingライブラリはkmpには対応していますが、cmpには対応していません。
つまり、

- `androidx.paging:paging-common` <- 使用可能
- `androidx.paging:paging-compose` <- 使用不可能

ということです。
じゃあ、Composeで使う場合Pagingは自分で実装しなきゃいけないじゃん

一応CashAppから[multiplatform-paging](https://github.com/cashapp/multiplatform-paging)というライブラリが出ており、そちらを使用することが可能です。
こちらのライブラリは、AndroidXのPagingにMultiPlatform用の処理を追加したり、ios用の`paging-uikit`などを追加したりするライブラリになっています。

READMEのInteroperability with AndroidX Pagingを見ていただくと`paging-common`の実装は同じであり,AndroidXのpagingライブラリと相互運用も可能と書いてあります(Paging3に限る)。

そのため、KmpとしてPaging3ですでに書いてあってもrefactorする必要はなく、CMPで使用したい場合は、cashappの`paging-compose-common`を追加して、実装することが可能です。

```toml
# これが可能
androidx-paging-common = { group = "androidx.paging", name = "paging-common", version.ref = "androidx-paging" }
cashapp-paging-compose = { group = "app.cash.paging", name = "paging-compose-common", version.ref = "paging-compose" }
```

## File指定
Desktopアプリでは、たびたびFileを指定して何かをすることが多々あると思います。自分で作るとだいぶめんどうな部類の話になると思いますが、[Filekit](https://github.com/vinceglb/FileKit)を使うと特にそこまで困ることはなく実装できます。
※一応beta段階なので今後に期待
```kotlin
// main.ktのapplication内
FileKit.init(appId = "MyApplication")

// compose内
val launcher = rememberFilePickerLauncher(
    mode = FileKitMode.Multiple(),
    type = FileKitType.Image,
) { files ->
    // file listが帰ってくる
}

// file選択の実行
launcher.launch()
```
これでFile選択を実装することができます。modeやtypeなどは必要に応じて指定するとUserが指定したfileを取得することができます。

## Mouse操作
Mouse操作に関してもExperimentalではあるものの実装できます。
- Mouseの移動イベント
```kotlin
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Move) {
            val position = it.changes.first().position
        }
){}
```

- MouseのHoverイベント
```kotlin
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Enter) { 
            // hover
        }
        .onPointerEvent(PointerEventType.Exit) { 
            // leave
        },
){}
```

- MouseのScrollイベント
```kotlin
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Scroll) {
            val dy = it.changes.first().scrollDelta.y
        }
){}
```

- MouseのDrugイベント
```kotlin
Box(
    modifier = Modifier
        .onDrag {
            val offset: Offset it
        }
){}
```

# まとめ
新しくアプリを作るのであれば、CMPという手段もなしではないと思う。
しかし、Win32APIなどOSのAPIを使用したりする場合、C Interopなどを実装しなくては行けなく、自分なら使わないかなぁと思う。

意外とそこまで困ることもそんなになくいけんくない
使ったっていいし、使わなくったっていい
Djangoテストケースの実行の仕方

## 1. 基本的なテスト実行コマンド
プロジェクトのルートディレクトリ（manage.pyがある場所）で以下を実行：
```terminal
python manage.py test
```
これはアプリ全体のテストをすべて実行します。

## 2. 特定アプリだけをテストする
たとえば api_app だけをテストしたい場合：
```terminal
python manage.py test api_app
```
## 3. 特定のクラスやメソッドだけをテストする
たとえば、api_app.tests モジュールの APITest クラス全体をテスト：
```terminal
python manage.py test api_app.tests.APITest
```
特定のメソッドだけをテスト（例：test_memo_create）：
```terminal
python manage.py test api_app.tests.APITest.test_memo_create
```
## 4. テストの出力を詳しくしたいとき
出力を詳しく（verbose）したいときは -v 2 を付けます：
```terminal
python manage.py test -v 2
```

## ⚠️ 注意点
テストは自動で テスト用データベース を作成・使用し、終了後に削除されます。
setUp() で作成したユーザーやデータは各テストで初期化されます。
Salesforce Sandbox 種類について

本橋孝昭です。

今回はSalesforceの　Sandbox種類と使い方について解説をします


# Sandboxの種類
Sandboxの種類は4つの種類があります

- Developer Sandbox: メタデータのみをコピーし、開発やテストに適した環境。
- Developer Pro Sandbox: Developer Sandboxよりも大容量で、より多くのデータを扱う開発・テスト向け。
- Partial Copy Sandbox: メタデータとサンプルデータをコピーし、ユーザー受け入れテストや統合テストに適した環境。
- Full Sandbox: 本番環境のすべてのデータとメタデータをコピーし、負荷テストやステージングに最適。
- 
それぞれのSandboxは、用途やストレージ容量、更新頻度が異なります。
次にそれぞれのSandboxの特徴について解説します

## 1. Developer Sandbox
- 用途: 個人開発・小規模な機能テスト
- コピー範囲: メタデータのみ（カスタムオブジェクト、設定、コードなど）
- ストレージ容量: 約200MB
- リフレッシュ頻度: 1日に1回
- 特徴:
- 本番環境の構成はコピーされるが、データは含まれない
- 開発者が新しい機能を試したり、コードを作成するのに最適


## 2. Developer Pro Sandbox
- 用途: より多くのデータを扱う開発・テスト
- コピー範囲: メタデータのみ（Developer Sandboxと同様）
- ストレージ容量: 約1GB（Developer Sandboxよりも大容量）
- リフレッシュ頻度: 1日に1回
- 特徴:
- Developer Sandboxよりも多くのデータを保存できるため、より複雑なテストが可能


## 3. Partial Copy Sandbox
- 用途: 統合テスト・ユーザー受け入れテスト（UAT）・トレーニング環境
- コピー範囲: メタデータ＋レコードデータ（コピーするレコードデータはテンプレートで定義可能）
- ストレージ容量: 約5GB
- リフレッシュ頻度: 5日に1回
- 特徴:
- メタデータに加えて一部のレコードデータもコピーされるため、より実践的なテストが可能
- UATやトレーニング環境として活用されることが多い

## 4. Full Sandbox
- 用途: 負荷テスト・ステージング環境・フルスケールのUAT
- コピー範囲: 本番環境のすべてのデータとメタデータ
- ストレージ容量: 本番環境と同程度
- リフレッシュ頻度: 29日に1回
- 特徴:
- 本番環境と完全に同じデータ構成でテストできるため、システムリリース前の最終確認に最適
- 負荷テストやパフォーマンス検証に使用される



参考記事

種類別 Sandbox ライセンスおよびディスク使用制限

https://help.salesforce.com/s/articleView?id=platform.data_sandbox_environments.htm&type=5

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/94769d89-ca02-4eb2-9e57-b72b2c42945d.png)

![uploading...0]()