OmniAICreator/Qiita-1.07M huggingface dataset:
prismaのseedファイルを作りテーブルに初期データを投入する

# やりたいこと
prismaのマイグレーションをしたら、DBテーブルに初期データを投入したい

# やり方
userテーブルに対して初期データを入れるとします。

まず、prismaフォルダ配下に以下のようなseed.jsを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/8a0a7fe9-511d-98b7-06a0-cb80722273fd.png)

```ruby:seed.js
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

async function main() {
  console.log('Seeding data...');
  
  // ユーザーを作成する例
  const user1 = await prisma.user.create({
    data: {
      email: 'user1@example.com',
      password: 'password1',
      name: 'User 1',
    },
  });
  
  const user2 = await prisma.user.create({
    data: {
      email: 'user2@example.com',
      password: 'password2',
      name: 'User 2',
    },
  });
  
  // 初期データを追加する他の処理...
  
  console.log('Data seeding complete.');
}

main()
  .catch(err => {
    console.error('Error seeding data:', err);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
```

次に、package.jsonファイルのscriptsに以下を追記

```ruby:
{
  "scripts": {
    "seed": "node prisma/seed.js"
  }
}
```

最後、以下のコマンドを実行～
```ruby:
npm run seed
```

結果として、こんな感じで追加されました～
（すでに手動で一行目のデータを入れたため、2と3行目が今回の結果データとなる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/a734f45b-8667-7013-d6ba-13a058dff026.png)
spearmanr

import numpy as np
from scipy.stats import spearmanr

# Sample data
x = np.array([1, 2, 3, 4, 5])
y = np.array([5, 4, 3, 2, 1])

# Calculate Spearman correlation coefficient and p-value
corr, p_value = spearmanr(x, y)

print("Spearman correlation coefficient:", corr)
print("P-value:", p_value) # pvalue < 0.05 is better
コンテナ上でexecコマンドを実行させる際に陥った罠

最近DockerをREST APIで操作していて色々躓いています。
なんとかChat-GPTの力を借りてやっていっています。

今回は、作業しているコンテナから別のコンテナに対して任意のファイルを実行させようとしたときに詰まったことについて紹介していきたいと思います。

何に詰まったかというと、

自分のコンテナ→相手のコンテナのファイル
の実行でPHPのexec関数を用いて
```php
exec('docker exec コンテナID コマンド');
```
としていました。
が、まさかのPermission deniedされてしまいます。対象のコンテナ内のファイルの権限が777ではないため、権限不足になってしまいます。
今回は自分がやった対処法について話したいと思います。

# 素直にDockerのREST APIのexec用のAPIを叩きましょう
Dockerにはコンテナでコマンドを実行させるためのAPIが備わっています。
素直にそれを使いましょう。

使い方は
```php
//host.docker.internalはホストOS上にコンテナを立てたいときに用います。場合によって変えましょう
        $execUrl = "http://host.docker.internal:2375/containers/{コンテナID}/exec";
        $execParam = [
            "AttachStdout" => true,
            "AttachStderr" => true,
            "Cmd" => [
                "bash", "-c", "実行したいコマンド"
            ]
        ];
        $response = Http::withHeaders(['Content-Type' => 'application/json'])
            ->post($execUrl, $execParam);
        $array = json_decode($response->body(), true);
        $execId = $array['Id'];
```

これで、コンテナでのexecをしたときのIDが生成されます。
次に、このコンテナIDのコードを実行しましょう。

```php
        // コマンドを実行
        $startResponse = Http::post("http://host.docker.internal:2375/exec/$execId/start", [
            "Detach" => false,
            "Tty" => true
        ]);
```

これで、コードが実行されました。コードの実行結果を取得したい際は、

```php
$startResponse->body()
```

で取得できます。

ただこれ自体は問題があります。ログに出力されるものしか取得できない点です。
さらに、もし仮に実行するソースコードが間違えていてもエラーメッセージは取得できません。

```javascript
functin test{
    console.log('Hello World');
}

test();
```

では、Hello worldがbodyに格納されているのですが、もし仮にこのコードが間違えていたとしても、エラー文は取得できません。

そのへんはまだ自分も解決することができていないので、もし解決できたら記事にしたいと思います。

よろしくお願いします。
【c++】ABC353 A-D問題解説【ACコード付き】

# AtCoder Beginner Contest 353
B問題までの2完10分。
レートは331から380の49アップとなった。

C,D問題は翌日に解いたものになります。

https://atcoder.jp/contests/abc353

## A - Buildings

ビルがN個並んでいる。一番左のビルより高いビルの中で、一番左側にあるビルの場所を出力せよ。という問題。

左側2番目のビルから順番に探索し、一番左のビルより高いビルを見つけたらその場所を出力すればいい。もし一番左のビルより高いビルがなかったら-1を出力する。

```cpp
int N;
int A[100009];

int main()
{
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> A[i];
	for (int i = 1; i <= N; i++)
	{
		if (A[1] < A[i])
		{
			cout << i << endl;
			return 0;
		}
	}
	cout << -1 << endl;
	return 0;
}
```
## B - AtCoder Amusement Park

K人乗りのアトラクションにN人グループ並んでいる。前から順にグループを乗せていき、乗れないグループまで来たらアトラクションを出発させ、次のK人乗りのアトラクションにグループを乗せていく。何回アトラクションを出発させたらNグループ全員をアトラクションに乗せられるか。という問題。

NもKも10^2以下と制約が軽いので、何も考えずループを回す。

現在のアトラクションの空席数をcurrent_emptyで記憶しておきながらNグループ全て終わるまでループを回しながら、何回アトラクションを出発させたか（何回current_emptyを初期化したか）を覚えておけばOK。

最後のお客さんの出発をお忘れなく。

```cpp
using namespace std;

int N, K;
int A[109];

int main()
{
	cin >> N >> K;
	for (int i = 1; i <= N; i++) cin >> A[i];
	int count = 0;
	int current_empty = K;
	for (int i = 1; i <= N; i++)
	{
		if (current_empty >= A[i])
		{
			current_empty -= A[i];
		}
		else
		{
			current_empty = K;
			count++;
			current_empty -= A[i];
		}
	}
	if (current_empty != K) count++;
	cout << count << endl;
	return 0;
}
```

## C - Sigma Problem
ちょっと特殊な問題なので、問題文を読んだ方が早いかもです。

10^8を超えないもの同士の足し算の10^8余りは、和が10^8を超えたら10^8を1回引くのと同義であることを利用して解く問題。

余りを気にせず全ての数A1~ANがN-1回足しておいて、後半でいくつのペアが10^8を超えるか、つまり合計から10^8が何回引かれたかをしゃくとり法で求めます。

本番中はソートして数えるまでは思いついたのですが、しゃくとり法を思い出すことができず、二分探索で模索したらWAでした。O(logN)とO(1)の差を痛感。。

```cpp
long long N;
long long A[300009];
long long R[300009];
vector<long long> Q;

const long long INF = 1e8;

int main()
{
	cin >> N;
	long long total = 0;
	for(int i = 1; i <= N; i++)
	{
		cin >> A[i];
		Q.push_back(A[i]);
		total += A[i] * (N - 1);
	}
	// 昇順に並べる
	sort(Q.begin(), Q.end());
	// しゃくとり法
	for (int i = 0; i < N - 1; i++)
	{
		if (i == 0) R[i] = 0;
		else R[i] = R[i - 1];
		// ギリギリまで増やす
		while (R[i] < N - 1 - i && Q[R[i]] + Q[N - 1 - i] < INF) R[i]++;
		total -= INF * ((N - 1 - i) - R[i]);
		if (R[i] == N - 1 - i) break;
	}
	cout << total << endl;
	return 0;
}
```

## D - Another Sigma Problem
この問題はC問題と違い、総計から余りを求める問題なので、計算各所で余りを計算しながら進むことが許されている。

それぞれのA1からANまでの与えられる数が右辺に来る時と左辺に来る場合をそれぞれ別に足し合わせている。

右辺に来る時は単純で、i-1回足される。
左辺に来る時はペアの右辺の桁の数によって総計に加える数が変わるので、入力を受け取るときに何桁の数がいくつずつあるかをカウントしておく。

```cpp
const long long INF = 998244353;

long long N;
long long A[200009];
long long digits[200009];
long long dig_mul[19];

int main()
{
	cin >> N;
	long long total = 0;
	for (int i = 0; i <= 10; i++) digits[i] = 0;
	for (int i = 1; i <= N; i++)
	{
		cin >> A[i];
		digits[to_string(A[i]).size()]++; 
		total += A[i] * (i - 1);
		total %= INF;
	}
	// 10から10^9まで事前に計算しておく
	dig_mul[0] = 1;
	for (int i = 1; i <= 10; i++)
	{
		dig_mul[i] = 10 * dig_mul[i - 1];
		dig_mul[i] %= INF;
		digits[i] %= INF;
	}
	for (int i = 1; i <= N - 1; i++)
	{
		digits[to_string(A[i]).size()]--; 
		A[i] %= INF;
		for (int j = 1; j <= 10; j++)
		{
			long long tmp = digits[j] * dig_mul[j];
			tmp %= INF;
			total += A[i] * tmp;
			total %= INF;
		}
	}
	cout << total << endl;
	return 0;
}
```
Reactで個人開発 ビジネスマッチングアプリ②

# 進捗
[前回の記事](https://qiita.com/urakata_engineer/items/a1cb4bed860163d1174e)からちょこちょこ機能の開発を行っていました。

主に追加した機能は以下になります。

- ユーザーカードのスワイプアニメーションを実装
    - LIKEボタンを押すと、左にスライドしてフェードアウト
    - SKIPボタンを押すと、右にスライドしてフェードアウト
- ユーザーカードを複数枚用意し、1枚目をスワイプすると2枚目が表示されるように実装
- ユーザーカードがなくなった時のアラートを実装

# 実際の挙動
![画面収録 2024-05-13 11.53.33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511372/285aa66c-497c-78a5-1b4a-0ff40e971a4f.gif)


# 苦戦したこと
[質問記事](https://qiita.com/urakata_engineer/questions/d9bb2247c43181498c9d)も作ったのですが、useSpringの扱いが難しかったです。

そもそもReact超初心者の私はhookの概念も曖昧なまま実装していたので、

何をuseEffectで処理して、何をイベントハンドラで処理すればいいのかの切り分けが難しかったです。

結局、react-springのドキュメントを読み漁り、

そもそもの扱い方が違っていることがわかりました。。

（useSpringで定義したスタイルをハンドラで直接更新しても、アニメーションが検知されないため、startプロパティを使う）

ログを仕込んでエラー調査することと、ドキュメント読み込みの重要性を再確認できました。
ベンフォードの法則を確認するプログラム

# ベンフォードの法則
[ベンフォードの法則](https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%B3%E3%83%95%E3%82%A9%E3%83%BC%E3%83%89%E3%81%AE%E6%B3%95%E5%89%87)とは，自然界に現れる数値の１桁目の１から９の数字が，等しく分布するのではなく，偏って分布するという法則です．数学的には数字$i$($0\leq i\leq 9$)が現れる頻度は，
$$
\log_{10}(i+1)-\log_{10}i
$$
となり，具体的には次のようになります．

| $i$ | $\log_{10}(i+1)-\log_{10}i$ |
|---:|---:|
|1|30.1%|
|2|	17.6%|
|3|	12.5%|
|4|	9.7%|
|5|	7.9%|
|6|	6.7%|
|7|	5.8%|
|8|	5.1%|
|9|	4.6%|

# Pythonプログラムによるベンフォードの法則の検証
ある銀行に口座を開設し，初日に1円を預けることにします．利子が毎日元本を2倍にすると仮定し，この状況で毎日の口座残高を記録します．注目点は，通帳に記載される金額の最初の数字がどのように分布するかです．簡単のため，残高が10以上になったときに10で割り，常に1以上10未満の金額が得られるようにします．そして，その整数部分からヒストグラムを作成します．この手順を実装したPythonプログラムが以下になります．


```Python
import math
from collections import defaultdict

iteration = 10000000
val = 1
histogram = defaultdict(int)
for _ in range(iteration):
    histogram[int(val)] += 1
    val *= 2
    if val >= 10:
        val /= 10

for i in range(1, 10):
    print(
        f"{i}: {histogram[i]/iteration*100:7.4f}% {(math.log10(i+1)-math.log10(i))*100:7.4f}%"
    )
```

`histogram`に`defaultdict`を使っているので，存在しないキーの値は0として扱われます．これを実行すると，次の結果が得られます．`val = 1`から開始しているので，小さい値の頻度が理論値より僅かに大きくなっています．

```
1: 30.1033% 30.1030%
2: 17.6092% 17.6091%
3: 12.4939% 12.4939%
4:  9.6910%  9.6910%
5:  7.9181%  7.9181%
6:  6.6945%  6.6947%
7:  5.7991%  5.7992%
8:  5.1152%  5.1153%
9:  4.5756%  4.5757%
```

`val`の初期値1を変更したり，利子を2倍でなく他の利率，例えば，1.001にしても同様の結果が得られます．
vscodeでSQLite

## 1.拡張機能でSQLiteをインストール
拡張機能検索で「SQLite」で表示される羽のアイコン。

## 2.ファイルを作成
ここでは、仮としてTest.dbを作成。

## 3.NewQuery
コマンドパレット(ctrl + shift + p)でSQLite opendatabase →　2で作成したファイルを選択

ファイルを開いていれば上記をしなくてもよい。![スクリーンショット 2024-05-13 114156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789121/b48b1ae1-af42-e4c3-c6f6-96fdb6bc3ad8.png)
ファイルを右クリックして、「**NewQuery**」を選択。


## 4.テーブル作成
開かれた「-- SQLite」の下にテーブル作成のSQLを書く。
例）
CREATE TABLE emp(empid INTEGER NOT NULL PRIMARY KEY, empname TEXT NOT NULL, email NOT NULL);

記入したら、「**ctrl + shift + Q**」でRun Queryが実行されます。この動作は、右クリックから選択でも可能です。

以下のようなタブが開きます。

## 5.データの挿入
先程記述した、SQL文をコメントアウトしその下にデータの挿入をするSQL文を記述します。
例）
INSERT INTO emp(empid,empname,email)
VALUES(1,"sam","test1@test.com");

記入したら、再度「**ctrl + shift + Q**」で実行。
**この時点では、目に見える変化はありません。**

## 6.テーブルのデータを取り出す（表示）
5のSQL文をコメントアウトし、SELECT文を記述します。
例）
SELECT * FROM emp;

記入したら、再度「**ctrl + shift + Q**」で実行。
すると、データを挿入されたテーブルが表示されます。

![スクリーンショット 2024-05-13 120344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789121/ad0bfa8a-0cad-8380-5a73-15320b7869c6.png)


# 以上！！
AWS・Azureのネットワーク系セキュリティサービスをまとめてみた

## はじめに
AWS・Azureのネットワークセキュリティサービスって覚えにくくないですか？
何のサービスが何を保護してくれるのか、今回改めてまとめてみました。

## 一般的に利用されるネットワークセキュリティ
前提として一般的なネットワークセキュリティの知識を少し書きます。
### ファイアウォール
ファイアウォールはネットワークレベルでトラフィックを監視及び制御します。
通信の送信元情報と送信先情報（IPアドレス、ポート番号等）を基にして、アクセスを制御します。
不正アクセスやネットワーク攻撃からネットワークを保護することが主な目的です。

### WAF
Web Application Firewallの略であるWAFはその名の通り、Web アプリケーションのセキュリティを強化します。
Webアプリケーションレベルでの攻撃（SQLインジェクション、クロスサイトスクリプティング等）を検出及び防御します。
Web アプリケーションの脆弱性を保護することが主な目的です。

### IDS/IPS
IDS/IPSはネットワークやOS・ミドルウェアへの攻撃を検知・防御します。
IDS（不正侵入検知システム）はその名の通り脅威を検知します。
一方、IPS（不正侵入防止システム）は脅威を検知し、さらに防御を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115411/e2f067c1-cb52-fb6d-f6b3-2049ed4f6a0f.png)

## AWS・Azureにおけるネットワークセキュリティサービス
AWS・Azureでは以下の図のように各サービスがネットワークを保護しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115411/4a973e98-ff36-441e-34fe-a293bbe6f74e.png)

* WebアプリケーションについてはAWS WAF/Azure WAFを利用して保護することが可能です。

* サーバやOS、ネットワークへの攻撃について、DDoS攻撃についてはShield/DDoS Protectionを利用して防御することが可能です。

* ネットワーク層を利用した攻撃については、AWS Network Firewall/Azure Firewallを利用して保護できます。
なお、AWS Network Firewall/Azure Firewallでは、IDS/IPS機能も提供されています。

* 脅威検出サービスであるGuardDuty、Inspector/Microsoft Defender for Cloudは、IDSとも言えます。

## おわりに
まとめてみたら頭がすっきりしました。
kubectlのlabel selectorが意外と便利

# label selectorとは

こんな感じで特定のラベルを持つリソースをフィルターするヤツ。

```
kubectl get pods -l environment=develop
kubectl get node -l 'pool in (apl, ingress)'
```

# 等価ベース
`=`, `==`, `!=`が使える。

```
environment = production
tier != frontend
```

# 集合ベース
めっちゃ便利。

- キーが`environment`で値が`production` or `qa`のリソース
```
environment in (production, qa)
```

- キーが`tier`で値がではない`frontend` or `backend`のリソース、もしくはキーが`tier`のラベルを持たないすべてのリソース
```
tier notin (frontend, backend)
```

- キーが`partition`のラベルを持つすべてのリソース
```
partition
```

- キーが`partition`のラベルを持たないすべてのリソース
```
!partition
```

# 参考

https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
【ChatGPT＋DALL-E3】連続で画像生成する方法（Select機能版）


　どうも、カーブミラーです。

　今回は、昨日に引き続き、連続で画像生成する方法です。“Select機能版”と書きましたとおり、一部の修正を連続して行ないます。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　これ、前に書きましたが、

>　OpenAIは
　　日本時間5月14日（火）午前3時に
　　　「Spring Updates」と題し、
　　　　ChatGPTとGPT-4の
　　　　　アップデートに関する
　　　　　　ライブストリーミングを
　　　　　　　行うと発表。

2024/05/13上記の時間が違いました
>ライブ配信は、PT（米国太平洋時間）の5月13日（月）10時スタート。日本時間は14日（火）深夜2時となる。
　X-Twitter上では
　　その内容が取り沙汰されています。
　　　予想ですね。

2024/05/13上記の時間が違いました

　　“GPT-5ではない”と
　　　サム・アルトマンが
　　　　ポストしていたので
　　　　　可能性は低く、
　　　　　　有力なのは
　　　　　　　音声なんちゃら、とか。

　まぁ、
　　今夜、
　　　３時を楽しみに
　　　　しましょうか。
2024/05/13上記の時間が違いました
　３時ではなく、２時てした。
2024/05/13上記の時間が違いました


***
　さて、本題です。

　昨日（2024/05/12）は
　　YouTuberのKEITOさんの
　　　ポストをもとに書きました。
[【ChatGPT＋DALL-E3】連続で画像生成する方法。](https://qiita.com/kabumira/items/0a72f10c290959475c23)

　今日は
　　その続きです。

　同じ画像で
　　一部だけを
　　　変えていきたい、
　　　　そう思ったことは
　　　　　ありませんか？

　私はあります。

　ということで
　　やってみました。
***
***user***
18歳金髪碧眼女性。ゆるふわロング。白いドレス。リアル。正方形で描画

***ChatGPT***
![1715564820216.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/de9349ad-8b36-507c-3142-9c42b5301704.jpeg)

***user***
（ドレスだけをSelect）
ドレスの色を（色）にしてください。

（色）は変数です。内容は任せます。

必ず1枚生成したら続けて生成して。5回続 けてください。

***ChatGPT***
![Screenshot_20240512-193802~3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/ef2ba9a9-2a42-9215-b7a6-2f608442f703.png)
***

　このように
　　一部だけの修正を
　　　連続して行なえます。

　❗注意点がふたつ。
　　❶確実とは言えない
　　❷連続しての描画は
　　　　DALL-E3の制限に
　　　　　達しやすい。

　　❶は上記で言えば、ドレスが変わる
　　　などの変化があります。

　　❷は以下のメッセージが出ます。
![Screenshot_20240513-103111~2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/de58f0d7-bc89-d383-b0b1-fb9016d9f091.png)
　とりあえず、
　　この二点には
　　　ご注意をお願いします。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
【基本情報技術者試験】ソフトウェア開発手法について説明する

６月末に基本情報技術者試験を受ける予定のエンジニアです。
今回は色々あるソフトウェア開発手法について説明したいと思います。
# 開発手法の種類
今回は以下の手法について簡単に説明していきます。
- ウォーターフォールモデル
- アジャイル開発
    - XP（エクストリームプログラミング）
    - スクラム開発
- プロトタイピングモデル
- スパイラルモデル
- リバースエンジニアリング
- DevOps

# ウォーターフォールモデル

ウォーターフォールモデルは、古典的なソフトウェア開発手法の代表格です。このモデルでは、開発プロセスが一連の段階に分かれ、次の段階に進む前に前段階が完了する必要があります。一般的な段階は、要件定義、設計、実装、テスト、展開、および保守です。

この手法の利点の一つは、段階ごとの明確な進行があります。各段階が完了した後に修正が行われるため、後続の段階での問題や変更が少なくなる傾向があります。また、各段階での成果物が文書化され、プロジェクトの進行状況を把握しやすいという利点もあります。

しかし、ウォーターフォールモデルにはいくつかの課題もあります。最初の段階での要件定義の不備や変更が後の段階での大幅な再設計を招く可能性があります。また、顧客とのコミュニケーションが限られているため、最終的な製品が顧客のニーズに適合しない場合があります。

# アジャイル開発

アジャイル開発は、ウォーターフォールモデルのような従来の段階的アプローチに代わるものとして登場しました。アジャイルでは、柔軟性、迅速性、および顧客のフィードバックを重視します。XP（エクストリームプログラミング）とスクラム開発は、その代表的な手法の一部です。

アジャイル開発の利点には、顧客との密接な連携による要件の柔軟な変更への対応があります。また、小さな成果物を短期間で提供するため、市場への早期リリースやフィードバックの獲得が可能です。
一方で、アジャイル開発には、適切な文化やプロセスが必要であり、従来の開発手法とは異なるチームの働き方が求められます。
### XP
XPは、テスト駆動開発（TDD）、ペアプログラミング、継続的インテグレーションなどのプラクティスを採用し、高品質なソフトウェアの開発を目指します。
### スクラム開発
スクラム開発は、プロジェクトを短い期間で分割し、各期間を繰り返すスプリントと呼ばれるサイクルで開発を進めます。スクラムでは、定期的な振り返りを通じてプロセスの改善を行います。



# プロトタイピングモデル

プロトタイピングモデルは、開発プロセスの早い段階で試作物を作成し、ユーザーのフィードバックを取得する手法です。これにより、要求の理解や設計の検証が容易になります。
プロトタイピングでは、ユーザーが直接製品の操作やデザインを評価し、開発チームはそのフィードバックを元に製品を改善していきます。

プロトタイピングの利点には、要求やデザインの不明確さに対応できることが挙げられます。また、ユーザーとのコミュニケーションを重視するため、最終的な製品がユーザーの期待に適合しやすくなります。
ただし、プロトタイピングには、試作物の作成やフィードバックの収集に時間と労力がかかるという課題があります。

# スパイラルモデル

スパイラルモデルは、リスク管理を重視した開発手法であり、ウォーターフォールモデルとプロトタイピングモデルの組み合わせと言えます。このモデルでは、開発プロセスが螺旋状に進行し、各段階でリスクの分析と評価が行われます。リスクの高い領域に重点を置き、試作物を作成することでリスクを低減します。

スパイラルモデルの利点には、リスクの早期発見と対処が可能であることが挙げられます。また、プロジェクトの進行状況に応じて柔軟にプロセスを調整できる点も利点の一つです。
しかし、スパイラルモデルは、リスク管理に時間と労力がかかるため、小規模なプロジェクトには適していない場合があります。

# リバースエンジニアリング

リバースエンジニアリングは、既存のソフトウェアやシステムを解析し、その仕組みや構造を理解する手法です。リバースエンジニアリングでは、ソースコードやバイナリコードを解析し、プログラムの機能やデータ構造を抽出します。これにより、既存のシステムの改善や互換性の確認、逆コンパイルなどが可能になります。

リバースエンジニアリングの利点には、既存のシステムの理解や改善が容易になることが挙げられます。また、リバースエンジニアリングによって得られた知識は、新しいプロジェクトの開発に役立ちます。
一方で、リバースエンジニアリングには、著作権やライセンスの問題が存在する場合があります。また、解析対象が複雑な場合、正確な理解に時間と労力がかかることがあります。

# 終わりに
このようにさまざまな手法があります。こんなに種類があることは知らなかったのでどれがどれだかわからなくなりそうですが、記憶しておきたいと思います。
ここまで読んでくださり、ありがとうございます。
機械学習用の画像前処理を解決!

## できること
![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577096/ba2f206f-d051-7f00-e5a5-f58feec33199.gif)
**いつも面倒な前処理を解決！！！**

## 背景
Stable Diffusion等の画像生成AIをファインチューニングしようとした際、なるべく綺麗な画像（背景情報などが削除された画像）を使いたい。しかし、背景を削除するのは一苦労。さらに、車などの対象物のサイズもバラバラだと学習もうまくいかなかったりする。そこで、背景を削除すると同時に、対象物のサイズも揃えた画像を出力できる本スクリプトを開発。さらに、UIも開発することで誰でも簡単に画像前処理ができるようにしました。

## 実行方法
https://github.com/Jake110ii/img2removeback/tree/main?tab=readme-ov-file

githubにソースコードはまとめていますので、gitに慣れている方は以降の記事をスキップして早速使ってください！以降の記事では、cloneしてUIを起動するまでを説明します。

### git clone
```bash
git clone https://github.com/Jake110ii/img2removeback.git
```

### create vertual env(任意)
```bash
pipenv shell
```
pipenvの参考: https://qiita.com/y-tsutsu/items/54c10e0b2c6b565c887a

### module install
```bash
pip install -r requirements.txt
```
必要なpythonライブラリをまとめてインストールします。

### run script
```bash
python main.py
```
これでUIの起動は完了です。http://127.0.0.1:7800/ にアクセスするとUIが起動されているはずです。どうぞ楽しい前処理Lifeをお送りください。
GitHub Actions を使って Git サブモジュールを自動更新する方法

### はじめに
この記事では、GitHub Actionsを利用してGitサブモジュールを自動的に更新するワークフローの設定方法を説明します。

### GitHub Actionsを使ったサブモジュールの自動更新設定

GitHubリポジトリで `.github/workflows` ディレクトリに以下の内容でワークフローファイルを作成します。

```yaml
name: Update Submodules

on:
  schedule:
    - cron: '0 0 * * *' # 毎日 UTC 0時に実行されます。
  workflow_dispatch: # このワークフローを手動で起動できるように設定します。

jobs:
  update-submodules:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout the repository
      uses: actions/checkout@v3
      with:
        fetch-depth: 0 # 全ての履歴とサブモジュールをフェッチします。
        
    - name: Update submodules
      run: |
        git submodule update --init --recursive
        git submodule update --remote
        
    - name: Commit and push changes
      run: |
        git config --global user.name 'Your Name'
        git config --global user.email ${{ secrets.USER_EMAIL }}
        git commit -am "Automatically update submodules"
        git push
```

#### GitHub Secretsの使用
'Your Name'はご自身のGiHubの名前に変更してください。
GitHubのSecretsを活用することで、メールアドレスなどの機密情報をセキュアに管理できます。
リポジトリの **Settings** → **Secrets** → **Actions** で `USER_EMAIL` としてメールアドレスを設定します。

#### Github Actionsの権限付与
以下記事を参考にGithub Actionsでリポジトリ更新ができるように権限付与が必要です。
https://zenn.dev/osawa_koki/articles/a63b96a2707a8f

### 設定例
https://github.com/setodeve/CatalogEasy/blob/main/.github/workflows/autoupdatesubmodule.yml

### まとめ
この設定を行うことで、サブモジュールを自動的に最新の状態に保つことができます。

### 参考資料
https://zenn.dev/ymmmtym/articles/dc741561759a49
Transporterでのエラー回避

# 経緯
Transporterで.ipaファイルをアップロードする際に遭遇したエラー。
再度遭遇した時に忘れそう（自分が）なので、自分用の備忘録です。

# 事象① XCodeのバージョンエラー

```bash
Asset validation failed (90725)
SDK version issue. This app was built with the iOS 16.2 SDK. All iOS and iPadOS apps must be built with the iOS 17 SDK or later, included in Xcode 15 or later, in order to be uploaded to App Store Connect or submitted for distribution.（ID: 15f56780-f9f6-410b-bcee-e6317f03bd06）
```
## 解決法

monacaクラウドIDEの　「設定＞ビルド環境の設定」　から、XCodeの項目を確認。
私の場合はバージョンを15以上にするようなエラーだったため
15.0.1を選択。

![スクリーンショット 2024-05-13 11.30.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224077/70481ea5-2c6c-74a0-f67c-773380fbfeda.png)


# 事象② BundleIDのバージョンエラー

```bash
The provided entity includes an attribute with a value that has already been used (-19232)
```

## 解決法

monacaクラウドIDEの　「設定＞iOSアプリ設定」　から、バンドルバージョンを修正。
以前Transporterにあげた時の.ipaファイルのバージョンよりも低いとNG。
私は前回「1.0.1」で上げていたので、「1.0.2」と修正しています。

![スクリーンショット 2024-05-13 11.30.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224077/4a4493cc-ad92-70f6-8720-f47ecf87a9d6.png)
AWS Lambdaで、LINE Botにローディングアニメーションを表示

# ローディングアニメーション
Messaging APIに、ローディングアニメーション表示機能が追加されました。

https://developers.line.biz/ja/news/2024/04/17/loading-indicator/


メッセージを送信してから返答が来るまでの間、指定した秒数だけローディングアニメーションが表示されます。また、表示中に返答が来ると自動的に消えます。

<img width="500" alt="loading_animation.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/ae361b6f-c45c-5f33-9b08-071ccf1370cf.gif">

# 実装
既にGASで実装した記事は出ているため、今回は、AWS Lambdaで実装しました。
ローディングアニメーションの部分だけ抜き出すと下記のようになります。

UserIDは環境変数から取得しています。

```lambda.py
# LINE Botの設定
line_config = {
    'channelSecret': os.environ['CHANNEL_SECRET'],
    'channelAccessToken': os.environ['CHANNEL_ACCESS_TOKEN'],
}    

# ローディングアニメーション
url_loading = "https://api.line.me/v2/bot/chat/loading/start"
headers_loading = {
    "Content-Type": "application/json",
    "Authorization": f'Bearer {line_config["channelAccessToken"]}'
}
payload_loading = {
    "chatId": UserID,
    "loadingSeconds": 20
}
response = requests.post(url_loading, headers=headers_loading, data=json.dumps(payload_loading)) 
```
以前書いた記事に、こちらを追加すると下記のようになります。

↓ 以前書いた記事

https://qiita.com/mamoru-ngy/items/e0c1df5b65412dbd2c84

```lambda.py
import os
import json
import boto3
import requests
import csv
import io

# GPTのAPIKEY
OPENAI_API_KEY = os.environ['OPENAI_API_KEY']

# UserID
UserID = os.environ["UserID"]

# AWS Lambdaハンドラー関数
def lambda_handler(event, context):
    
    # LINE Botの設定
    line_config = {
        'channelSecret': os.environ['CHANNEL_SECRET'],
        'channelAccessToken': os.environ['CHANNEL_ACCESS_TOKEN'],
    }    
    
    # ローディングアニメーション
    url_loading = "https://api.line.me/v2/bot/chat/loading/start"
    headers_loading = {
        "Content-Type": "application/json",
        "Authorization": f'Bearer {line_config["channelAccessToken"]}'
    }
    payload_loading = {
        "chatId": UserID,
        "loadingSeconds": 20
    }
    response = requests.post(url_loading, headers=headers_loading, data=json.dumps(payload_loading)) 
        
    # Lambdaクライアントの作成
    lambda_client = boto3.client('lambda')
    
    # S3のバケット名とファイルキーを取得
    bucket_name = 'linebot-text'
    file_key = 'linebot_text.csv'

    # S3オブジェクトを取得
    s3 = boto3.client('s3')
    
    # S3からファイルをダウンロードしてcsvデータを読み取る
    response = s3.get_object(Bucket=bucket_name, Key=file_key)
    data = response['Body'].read().decode('utf-8')

# 以下省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
```

# 最後に
実装にそれほど時間はかかりませんでした。
ユーザーがちゃんと送信できていることを確認できますし、返答を待つ時間のストレスを軽減できるのではないかと思います。
pod update で CDN: trunk URL couldn't be downloaded: https://cdn.cocoapods.org/Specs/.... Response: Failure when receiving data from the peer というエラーが発生

# 背景
CocoaPods を使用しているプロジェクトで `pod update` を行った際に以下のエラーが発生しました。

```sh
$ pod update                          
Update all pods
Updating local specs repositories
Analyzing dependencies
[!] CDN: trunk Repo update failed - 2 error(s):
CDN: trunk URL couldn't be downloaded: https://cdn.cocoapods.org/Specs/0/3/5/Firebase/10.24.0/Firebase.podspec.json Response: Failure when receiving data from the peer
CDN: trunk URL couldn't be downloaded: https://cdn.cocoapods.org/Specs/0/3/5/Firebase/10.25.0/Firebase.podspec.json Response: Failure when receiving data from the peer
```

# 対応
`~/.cocoapods/repos/trunk/Specs` ディレクトリ以下のファイルを全て削除することで解決しました。

```sh
$ rm -rf ~/.cocoapods/repos/trunk/Specs/*
```

`~/.cocoapods/repos/trunk/Specs` ディレクトリ以下を削除することで問題が解決する理由は、CocoaPods がローカルに保存しているリポジトリのキャッシュをクリアし、再度リポジトリ情報を全て新規にダウンロードするためです。キャッシュが破損していたり古い情報が含まれている場合、それが原因でダウンロードに失敗することがあります。キャッシュを削除することで、最新かつ正確なデータをサーバーから取得するため、問題が解消されることが多いです。

# Specs ディレクトリについて
`~/.cocoapods/repos/trunk/Specs` ディレクトリには、CocoaPods の Trunk リポジトリの仕様（Specs）が含まれています。このディレクトリは、CocoaPods が利用可能な各ポッドのバージョン、依存関係、ソースの場所などのメタデータを格納した .podspec ファイルをキャッシュしておく場所です。各ポッドの設定情報が、階層的なディレクトリ構造で保存されています。

例えば、ある特定のライブラリ（例：Firebase）のすべてのバージョンの .podspec ファイルがここに配置されています。これにより、pod install や pod update が実行される際に、どのバージョンのポッドが必要で、どの依存関係が存在するかを CocoaPods が解決できるようになります。

`~/.cocoapods/repos/trunk/Specs` ディレクトリを削除しても、通常は問題は起きません。CocoaPods はこのディレクトリを自動的に再生成し、必要な .podspec ファイルを再ダウンロードします。これは基本的にはキャッシュをクリアする行為に等しく、古いまたは破損したデータが原因で発生している問題を解決するのに役立ちます。

# 参考
https://github.com/CocoaPods/CocoaPods/issues/12304
Moon: タスクでglobパターンが展開されてしまうのを防ぐ方法

## はじめに

moonrepoのタスクはコマンドを実行するための便利な仕組みです。シンプルな例だと次のように書けます。

```yaml
tasks:
  hello:
    command: echo Hello World
```

しかし、`command`にglobパターンを使用すると、意図せずmoonによって展開されてしまうという落とし穴があります。

例えば、moon.yamlにて、`echo hello *`というコマンドをcommandに書いて実行すると、

> hello moon.yaml

のような出力が得られてしまいます。これは、`*`がmoonによって解釈され、コマンドを実行したディレクトリにある`moon.yaml`ファイルのファイル名に変換されてしまうためです。ちなみにこの現象はmoon 1.24.4で確認しました。


## Globの展開を防ぐ方法

この問題を防ぐには、`tasks.*.options.shell`を`false`に設定します。

```yaml
tasks:
  hello:
    command: echo 'hello *'
    options:
      shell: false
```

これにより、意図せずglobが展開されることはなくなります。

## 様々な実験

この解決策に至るまで、いくつかの実験を行ったので、そのコードを共有します。

```yaml:moon.yml
$schema: https://moonrepo.dev/schemas/project.json

tasks:
  demos:
    deps:
      - demo1
      - demo2
      - demo3
      - demo4
      - demo5
      - demo6
      - demo7

  demo1:
    command: echo 'hello *'
    inputs: []
    options:
      cache: false

  demo2:
    command: echo "hello *" 
    inputs: []
    options:
      cache: false

  demo3:
    command: echo "hello **/*"
    inputs: []
    options:
      cache: false

  demo4:
    command: echo hello *
    inputs: []
    options:
      cache: false

  demo5:
    command:
      - echo
      - hello
      - "*"

  demo6:
    command: echo
    args:
      - hello
      - "*"

  demo7:
    command: echo 'hello *'
    options:
      shell: false
```

ディレクトリ構成は以下の通りです。

```
.
├── dir1
│   └── dir2
│       └── dir3
│           └── file
└── moon.yml
```

実行結果は次のようになります。

```
❯ moon run -c 1 :demos
▪▪▪▪ demo:demo1 
▪▪▪▪ demo:demo1 (34ms)
::: zshenv :::
hello dir1 moon.yml

▪▪▪▪ demo:demo2
▪▪▪▪ demo:demo2 (33ms) 
::: zshenv :::
hello dir1 moon.yml

▪▪▪▪ demo:demo3
▪▪▪▪ demo:demo3 (34ms)
::: zshenv :::
hello dir1 dir1/dir2 dir1/dir2/dir3 dir1/dir2/dir3/file moon.yml

▪▪▪▪ demo:demo4
▪▪▪▪ demo:demo4 (34ms)
::: zshenv ::: 
hello dir1 moon.yml

▪▪▪▪ demo:demo5 (cached from previous run, 1a74b9e1)
::: zshenv :::
hello dir1 moon.yml

▪▪▪▪ demo:demo6 (cached from previous run, 011b7238)
::: zshenv :::
hello dir1 moon.yml  

▪▪▪▪ demo:demo7 (cached from previous run, 6f4e067f)
hello *

▪▪▪▪ demo:demos (cached from previous run, f5fc3c10)

Tasks: 8 completed (4 cached) 
Time: 160ms
```

demo7の`shell: false`以外はことごとくglobが展開されてしまっているのが分かります。

## まとめ

moonrepoのタスクでglobパターンが意図せず展開されてしまう問題は、`tasks.*.options.shell`を`false`に設定することで回避できます。
様々なパターンを試してみましたが、この方法が一番スッキリと解決できました。
moonを使う際は、このような落とし穴にも気をつけながら、快適なタスク管理を行っていきましょう。
Laravel + nextjsのdocker環境構築・プロジェクト立ち上げ

## 1.導入環境
- M1 pro macbookpro(os:sonoma:14.4.1（23E224）)
- docker desktop
---
## 2.ディレクトリ構成
```
├── README.md
├── backend
│   └── Dockerfile
├── compose.yaml
├── db
│   └── my.cnf
├── frontend
│   ├── Dockerfile
│   ├── laravel-next
│   └── package-lock.json
└── mysql
    └── my.cnf
```
---

## 3.各ディレクトリのDockerfileとCompose.yaml
```Dockerfile:frontend/Dockerfile
#node.jsを採用
FROM node:20.12.2

#作業ディレクトリの設定
WORKDIR /app
```
```Dockerfile:backend/Dockerfile
#php8.3を使用するためのDockerfile
FROM php:8.3-apache

RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip \
    unzip \
    && docker-php-ext-install zip pdo_mysql mysqli

#composerのインストール \
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

#apacheの設定
RUN a2enmod rewrite
```
---
```Yaml:compose.yaml
version: "3.8"
services:
  frontend:
    build:
      context: /frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    volumes:
      - .:/pages
    working_dir: /pages
    tty: true
    stdin_open: true


  backend:
    build:
      context: /backend
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    volumes:
      - backend:/var/www/html
    working_dir: /var/www/html

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - .db:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
```
Dockerfileとcompose.yamlを作成したら
```
docker compose build -d 
```
## 4.laravelプロジェクト・nextのプロジェクトを新規で作成する
#### laravel側の新規プロジェクトの立ち上げ方
```
composer create-project "laravel/laravel=バージョン" プロジェクト名
```
#### next側の新規プロジェクトの立ち上げ方
```
npx create-next-app@latest
または
yarn create next-app
```
#### typescriptで始めたい人は
```
npx create-next-app@latest --typescript
または 
yarn create next-app --typescript
```
:::note info
基本的にはnext側のプロジェクトの立ち上げ方で大丈夫だと思いますが、チームの方針によって使い分けてください。
個人開発の方はnext側でプロジェクトを立ち上げることをお勧めします。
:::
---
### まとめ
今回はlaravel + nextjsのdocker環境構築方法についてまとめてみました。
皆様の問題解決の手助けになれていれば幸いです。

---
RaspberryPiでiCloudを利用する

## はじめに
この記事は自分用のメモに書いていますので、最低限の情報しか書いていませんがご了承ください。
## メモ
### インストール
1. snapのインストール
    ```bash
    $ sudo apt update
    $ sudo apt install snapd
    $ sudo reboot
    $ sudo snap install core
    ```
1. icloud-for-linuxのインストール
    ```bash
    $ sudo snap install icloud-for-linux
    $ sudo reboot
    ```
### 使用方法
- スタートメニュー　> オフィス内にiCloudの各アプリケーションのアイコンが追加されているのでそちらから起動する
- 初回起動時はログインが必要
HEICをjpgに変換するコード

## HEICをJPGに変換する
iPhoneで写真を撮る時デフォルトだとHEIC形式で保存されます。HEIC形式だと画像処理をする際何かと不便なので、pythonでjpgに変えてしまいましょう！

注意：iPhoneの設定を変えることでjpg形式で撮影することは可能です

## 前提条件
pyheifをインストール
```bash
pip install pyheif
```

## コード
```python: heic2jpg.py
import os
import pyheif
import shutil
from PIL import Image

# 入力フォルダと出力フォルダのパス
input_folder = "<input_folder>"
output_folder = "<output_folder>"

# 出力フォルダが存在しない場合は作成する
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

num = 0
# 入力フォルダ内の画像ファイルを走査して変換する
for filename in os.listdir(input_folder):
    num += 1
    # ファイルのパス
    file_path = os.path.join(input_folder, filename)
    
    # ファイルが画像ファイルであるかを確認する
    if os.path.isfile(file_path) and any(filename.endswith(ext) for ext in ['.jpg', '.jpeg', '.png', '.JPG', '.bmp', '.tiff', '.HEIC']):
        # HEIC形式の画像をJPEG形式に変換して保存
        if filename.endswith('.HEIC'):
            heif_file = pyheif.read(file_path)
            image = Image.frombytes(
                heif_file.mode, 
                heif_file.size, 
                heif_file.data,
                "raw",
                heif_file.mode,
                heif_file.stride,
            )
            output_file_path = os.path.join(output_folder, f'{num:04}' + '.jpg')
            image.save(output_file_path, "JPEG")
            print(f"{filename} を変換して {output_file_path} に保存しました。")
        else:
            # その他の画像形式の場合は単純にコピーする
            output_file_path = os.path.join(output_folder, f'{num:04}' + '.jpg')
            shutil.copy(file_path, output_file_path)
            print(f"{filename} をコピーして {output_file_path} に保存しました。")

print("すべての画像を変換しました。")

```

## 終わりに
iPhoneのデフォをjpegで取れるようにしてほしいです...
React　親コンポーネントのメソッドを子コンポーネントから使用する

# 親コンポーネントのメソッドを子コンポーネントから使用する

子コンポーネントで、削除処理などを実行した際に、
親コンポーネントのリストを更新したい。
といった場合にこのような処理が必要になった。解決に苦労したので備忘録とする。

※この記事は、殴り書きなので誤字脱字等あるかもしれません。
Markdown記法にも慣れていないため、以後また余裕のある時に更新します。
とりあえずメモ程度。


解決法。

親コンポーネント。
■Parent.tsx
```

-略-
export default function ParentComponent(this:any) {
    //子Componentに渡す処理部
    function updateList(searchWord: string): void {
        //リスト更新処理：searchWordで検索できる系
    }
    
    return (
        <>
            <ChildComponent giveMethod={updateList} />
    );
    -略-
}
```
子コンポーネント
■Child.tsx
```
//各import文

//Propsの設定
type Props = {
    giveMethod?:(context: String) => void;
};

-略-

//子コンポーネント
const ChildComponent :React.FC<Props> = (props) => {
    //使用する場所
    const useParentMethod = () => {
        props.giveMethod && props.giveMethod("");
    }
}
export default ChildComponent
```
propsでメソッドを子コンポーネントに渡して、子コンポーネントから親のメソッドを呼んであげる。
社内でも使えるOSS WikiのGrowiでメール設定をblastengineに変更する

[GROWI](https://growi.org/ja/)はオープンソースのWikiシステムです。社内の情報共有などで利用されています。GROWIにはメール送信機能がありますが、デフォルトでは特に設定されていません。そこで、[blastengine](https://blastengine.jp/)を利用してメール送信を行えるように設定する流れを紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/b9bf7815-998e-f9e1-3f44-b4047451c5bd.png)


## blastengineの設定

blastengineでは、SMTPの設定が必要です。必要な情報は以下の通りです。

| 項目 | 説明 |
| --- | --- |
| SMTPホスト | `smtp.engn.jp` |
| SMTPポート | 587 |
| SMTPユーザー | blastengineのユーザーID |
| SMTPパスワード | これから作成 |

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f0ad3f5c-f09e-0d93-d11a-653b1a56c9ac.png)


## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

DKIMも必要に応じて（なるべく）設定してください。

### SMTP用のパスワードを設定する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/78a4eeb3-4649-149f-8246-44f83d03a0cf.jpeg)

そして設定の中にあるSMTPリレーの項目で、SMTP用のパスワードを設定できます。IPアドレスベースの認証も可能ですが、今回は利用しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/e615c636-8bf6-0937-6ed6-d06e933b84c7.png)

## GROWIを立ち上げる

GROWIを立ち上げる一番簡単な方法は、Docker Composeを使うことです。

```bash
git clone https://github.com/weseek/growi-docker-compose.git growi
cd growi
docker-compose up -d
```

これで `http://localhost:3000` にてGROWIが立ち上がります。

![FireShot Capture 123 - インストーラー - GROWI - localhost 123.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ae6e2691-c1c4-2312-a2c9-d53c025e2905.jpeg)

### インストール

最初にアクセスすると、管理者登録が求められます。ユーザー名やパスワードを設定して完了します。

![FireShot Capture 124 - _ - GROWI - localhost 124.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/fbef0f85-0d63-5d1e-14b3-cd273e278e91.jpeg)


### メール設定

メール設定は `http://localhost:3000/admin/app` にあるアプリ設定より行います。項目は「メールの設定」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2c420eab-228b-d4cb-82fe-6c2143624008.png)


ここで、送信方法はSMTPを選択してください。そして、下記の項目を設定します。

| 項目 | 設定値 |
| --- | --- |
| SMTPホスト | `smtp.engn.jp` |
| SMTPポート | 587 |
| SMTPユーザー | blastengineのユーザーID |
| SMTPパスワード | 先ほど設定したSMTPパスワード |

また、Fromアドレスも適切に設定してください。設定したら、更新ボタンを押します。

### テストメールの送信

設定を更新したら、テストメールを送信してみます。右上に送信完了のメッセージが表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f78657b0-1a82-0ad5-9f87-237c29118ff5.png)


また、メールボックスにテストメールが届いているのが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/fc2d6d88-1740-30eb-17a0-b4d28179a8a0.png)


## まとめ

今回はGROWIで、blastengineを使ってメール送信を行う方法を紹介しました。ぜひGROWIとblastengineを組み合わせて使ってみてください。

[エンジニア向けメール配信システム「ブラストエンジン（blastengine）」](https://blastengine.jp/)
Microsoft Edge にて、Mobile と連携して Web Site にファイルをアップロードする

# これは何？
Microsoft Edge にて可能な [モバイルアップロード](https://www.microsoft.com/ja-jp/edge/features/mobile-upload?form=MA13FJ) の機能についての記事です。

# モバイルアップロードとは？
PC のファイル選択ダイアログ上に "モバイルからアップロード" ボタンが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/2c5a8501-b5fe-3c62-88dd-2b84d08f24fc.png)


こちらの押下からの一連のオペレーションで、QR コードを介して モバイルからファイルをアップロード可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/4d58705b-8962-fb40-e7ba-ff6dbb677e9d.png)

# 制限
下記の二つの制限があります。
・ ネットワークが同一のセグメントに所属していること
・ PC 側の Microsoft Edge のプロファイルにサインインしていること

後者の理由により、"ゲストモード" 及び "InPrivate モード" での利用は下記のようになり不可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/e6aba722-0d11-543c-2e68-5e02a5e724b0.png)

# セキュアであるかどうか
ネットワークの関係上、悪意ある外部からの干渉を受ける可能性は低いです。
一方で内部からの情報の流出などについては耐性がありませんので、もしご懸念の場合はポリシー "[UploadFromPhoneEnabled](https://learn.microsoft.com/ja-jp/deployedge/microsoft-edge-policies#uploadfromphoneenabled)" にて機能を無効にするのが良いかなと思います。
AWSを基本からまとめてみた【ELB】

## ELB（Elastic Load Balancing）とは？

- AWSが提供しているロードバランサのサービス
- 負荷分散(2代以上にアクセス分散・マルチAZ対応)ができる
- 正常なインスタンスにリクエスト(ヘルスチェック)
- マネージドサービスなので管理不要
- ELB自体もスケーラブル
- 空きIPアドレスが8つ必要(最低でもサブネット毎に/28(この場合はELB１台))
- オートスケーリングと組み合わせられる(必要時にターゲットを増減)

※ ロードバランサ・・・システム負荷のバランスをとるために処理を分散
※ リスナー・・・internet->ELB 対応するプロトコル、ポート番号
※ ターゲット(グループ)・・・ELBが通信を転送するEC2など

## ELBの種類
- ALB(Applicaton)・・・レイヤー７HTTP, HTTPSなどを負荷分散するロードバランサでwebアプリケーションによく利用する
- NLB(Network)・・・レイヤー4TCP, UDPなどで動作し、静的なIPアドレスを見るので、ALBのような細かい振り分けができないが、1秒あたりに数百万のリクエスト処理することができる
- GWLB(Gateway)・・・新しい。レイヤー3ネットワーク, 異なるVPCやAWSアカウント間で共有できる
- CLB(Classic)・・・ALBとNLBがリリースされる前のロードバランサ



## 参考サイト
[【AWS】【ELB】ロードバランサーについてわかりやすく解説してみた](https://www.youtube.com/watch?v=3w1yYc4LhN0)
[【CLF-C01：AWSクラウドプラクティショナー】第19回 ELB(テクノロジー分野)](https://www.youtube.com/watch?v=reJ75v5KPBU)
[Elastic Load Balancing【AWS Black Belt】](https://www.youtube.com/watch?v=gKCK0RDAhnw)
c++  vector<string> と同等の処理をC言語の動的配列で実装する


```cpp:code_only.cpp
std::vector<string> str5(5);
```

これをC言語の動的配列で行う
Visual Studio 2022 を使用

普段ならこんな面倒でタイパの悪い事はする気ない（Z世代のマネしてみた）が、
それに挑戦してみたいという人がいたので協力してみた。

１命令事に調べると時間がかかるので良さそうなサンプルを探したところ、提示されている方がおられたのでありがたく使わせていただくことにした。

https://qiita.com/matsuhandy/items/2d44666a6ab110fda93f

こちらのサイトのプログラムを改造してみて、code_only.cpp をC言語で実装するサンプル
※以下は、プロジェクトのプロパティ ＞ C／C＋＋ ＞ SDLチェック いいえ(/SDL-)  にしないと動作しません

```c:c_vecor.cpp
// std::vector<string> str5(5);

#include <stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include <string>

int main()
{
    char** a;
    unsigned v = 5, h = 20; // 配列５個
    unsigned i, j;

    a = (char**)calloc(v, sizeof(char*));
    for (i = 0; i < v; i++) {
 //       a[i] = nullptr;  // ワーニング消せなかった
        a[i] = (char*)calloc(h, sizeof(char));  // ワーニング消せなかった
    }

    const char* str[] = {"apple","banana","orange","pineapple","mango"}; // テストデータ
    for (i = 0; i < v; i++) 
    {
            strcpy(a[i],str[i]);
    }
    for (i = 0; i < v; i++) 
    {
            printf("%s\n",a[i]);
    }

    for (i = 0; i < v; i++) {
        free(a[i]);
    }
    free(a);

    return 0;
}

```


実行結果
```
apple
banana
orange
pineapple
mango


```

参考サイトが有るにも関わらず、伝えないのはありえないと思う。
参考にしたサイトが有れば必ず書きましょう。

C++のありがたみを実感できる形になった。
こんな面倒なことは普通はやらない。

しかし、きまぐれが起きたら、またやるかも知れない。



==== 追記 ====
ワーニング対策がこちらのサイトに書かれていました。
記事ではVisualStudio2019の対策
ワーニング消しに成功しました。

https://qiita.com/natetsu123/items/9724cb3d51fc4de70c78


<details close><summary>ワーニング対策コード（クリックで開きます）</summary>

```c:c_vector.c
#include <stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include <string>

int main()
{
    char** a;
    unsigned v = 5, h = 20;
    unsigned i, j;

    a = (char**)calloc(v, sizeof(char)*h);
    for (i = 0; i < v; i++) {
        if (a != nullptr)   // ワーニング消し
        {
            a[i] = (char*)calloc(h, sizeof(char));
        }
    }

    const char* str[] = {"apple","banana","orange","pineapple","mango"}; // テストデータ

    for (i = 0; i < v; i++) 
    {
        if (a != nullptr && a[i]!=nullptr)   // ワーニング消し
        {
            strcpy(a[i],str[i]);
        }
    }

    for (i = 0; i < v; i++) 
    {
        if (a != nullptr)   // ワーニング消し
        {
            printf("%s\n",a[i]);
        }
    }

    for (i = 0; i < v; i++) {
        if (a != nullptr)   // ワーニング消し
        {
            free(a[i]);
        }
    }
    free(a);

    return 0;
}

```
</details>
【Flutter】showDialog上でボタンを押した時に2個前のページに戻る

備忘録です。

```
一覧ページ -> 詳細ページ -> Dialogを表示 
```
というページ構成の場合に、
Dialog上であるボタンを押したら一覧ページまで一気に戻る、という動線がよくあると思います。
(削除ボタンとか)

この時、AlertDialog上で
```Dart
Navigator.popUntil(context, (route) {                
  return route.isFirst;
});
```
を実行しても一覧ページまで戻れません。
↓の感じにすると元のページ遷移も操作できます。

```Dart:example.dart
void showMyDialog(BuildContext parentContext) {
  showDialog(
    context: parentContext,
    builder: (BuildContext dialogContext) {
      return AlertDialog(
        title: Text('Confirm'),
        content: Text('Do you want to go back?'),
        actions: <Widget>[
          TextButton(
            child: Text('Yes'),
            onPressed: () {
              Navigator.of(dialogContext).pop(); // ダイアログを閉じる
              Navigator.popUntil(parentContext, (route) { // 元のページ遷移の最初に戻る
                  return route.isFirst;
                });
            },
          ),
        ],
      );
    },
  );
}
```

これは詳細ページが持つNavigatorStateとDialogの持つNavigatorStateが異なるため、
呼び出す対象のcontextを明示してあげる必要があります。
自然言語クエリからSQLへ：生成AIがもたらすデータ活用革命


サンプルのDBスキーマは、anthropic site  で公開されているTypical DB schema (Customers, Products, Orders, Orders_Items, Reviews)を使用しています。


DBスキーマのウェブサイトからテキスト全体をコピーし、Googleドキュメントに貼り付ける。 そして、Googleドキュメントに保存された内容をPDFファイルとしてエクスポートします。 その後、このPDFファイルをクロード（またはChatGPT）にアップロードし、コマンドを与えます： "10個の自然言語クエリとそれに対応するSQLステートメントを含むテーブルを作成する" 簡単でしょう？



(**このERD図は、クロードに"アップロードされたDBスキーマ対応するERDを描くPythonコードを生成してくれ "と依頼し、クロードが生成したPythonコードをコピーし、ChatGPTで実行すること作成されました。 **)

これにより、クロードはスキーマ情報に基づいて以下のことができる：

1. 自然言語クエリの理解
ユーザの自然言語クエリに現れるキーワードと DB スキーマのテーブル/カラム名を一致させる。
クエリで使用されている集約関数（SUM、AVG など）と条件（過去 1 年、上位 10 件など）を特定する。

2. SQL文の生成
特定されたテーブル/カラム、集約関数、条件を組み合わせて、正しい構文のSQL文を自動的に生成します。
必要に応じてテーブルJOINやサブクエリを使用する。

3. データ型を考慮する
列のデータ型（INT、VARCHAR、DATEなど）を考慮して適切な操作や比較を行う。
文字列を引用符で囲み、必要に応じて日付にデータベースに適した書式を使用する。

4. 検証と改良
生成されたSQL文が文法的に正しく、実行可能であることを検証する。
セキュリティ・リスク（SQLインジェクションなど）となり得る内容を削除する。

自然言語クエリとそれに対応するSQL文の例を20個紹介します：

Claude Prompt: 「20の自然言語とそれに対応するSQL文を表にしてください。
クロードの答え

自然言語クエリ
平均注文金額が100ドル以上の顧客のメールアドレスを取得する

SQLステートメント
SELECT email<br>FROM Customers<br>WHERE customer_id IN (<br>  SELECT customer_id<br>  FROM Orders<br>  GROUP BY customer_id<br>  HAVING AVG(total_amount) >= 100<br>);

amazon.co.jp「Claude 3 AIの活用 :文章作成およびビジネス業務 Kindle版」からの抜粋です。https://bit.ly/4dW1cNH
Kali Linux on WSL2 の win-kex  で xfce4 以外を使う

# はじめに

アップストリームで採用して欲しいけど、とりえあず win-kex の起動スクリプトを直接書き換える。
一応、i3wm に変更して問題なく動作している。

# 変更

XSTARTUP が定義されていたら、そちらを見るようにする。

```diff
*** kex.orig	Mon May 13 10:29:17 2024
--- kex	Mon May 13 10:29:35 2024
***************
*** 9,15 ****
  reset='\033[0m'
  
  WINKEXDIR="/usr/lib/win-kex"
! XSTARTUP="${WINKEXDIR}/xstartup"
  XRDPINI="/etc/xrdp/xrdp.ini"
  XRDPSERVICE="${WINKEXDIR}/xrdp/xrdpservice"
  XSERV="${WINKEXDIR}/VcXsrv/vcxsrv.exe"
--- 9,15 ----
  reset='\033[0m'
  
  WINKEXDIR="/usr/lib/win-kex"
! [[ -z "$XSTARTUP" ]] && XSTARTUP="${WINKEXDIR}/xstartup"
  XRDPINI="/etc/xrdp/xrdp.ini"
  XRDPSERVICE="${WINKEXDIR}/xrdp/xrdpservice"
  XSERV="${WINKEXDIR}/VcXsrv/vcxsrv.exe"

```

/usr/lib/win-kex/xstartup をホームディレクトリにコピー、最終行の startxfce4 を exec i3 に変更し、自分のホームディレクトリの xstartup で起動する

```shell
env XSTARTUP=$HOME/xstartup win-kex --win -s
```
conda + miniforge3を用いたPython開発環境の導入

# M2 Mac上におけるpython（開発）環境の構築の記録

参考
* [Pythonのパッケージ管理ベストプラクティス](https://qiita.com/c60evaporator/items/b6a7394231d1e768ce64#3-conda--conda-forge)
* [Conda + Miniforge3でM1 MacのPython開発環境を構築する](https://for.kobayashiii.dev/articles/67e1ce03th)

## Miniforge3のインストール

1. [Miniforge](https://github.com/conda-forge/miniforge#download)から``Miniforge3-MacOSX-arm64``をクリックしてダウンロードする（Python 3.10）。
1. ``Miniforge3-MacOSX-arm64.sh``が``Downloads``にダウンロードできたならインストーラーを実行する。
```
cd ~/Downloads
```
```
bash Miniforge3-MacOSX-arm64.sh
```
以下を実行してインストールできたことを確認する。
```
conda info
```
最後の質問
```
You can undo this by running `conda init --reverse $SHELL`? [yes|no]
```
でデフォルトの``no``を選ぶと``conda``へのパスが通らないので、以下を実行すると良い。
```
eval "$(~/miniforge3/bin/conda shell.bash hook)"
conda init
```
でもターミナルを立ち上げる度にこのコマンドを実行する必要があるので、上の質問には``yes``と答え、
```
conda config --set auto_activate_base false
```
を実行しておくのが良い。でもなぜか``conda``へのパスが通らない。
今は以下のコマンドを``~/.bashrc``に記載してある。
```
eval "$(~/miniforge3/bin/conda shell.bash hook)"
```
PHPカンファレンス香川2024に行ってきた話

# 初めに
Akira_0809です。
今回は初めてカンファレンスに参加したので、その話をしたいと思います。
ちなみに、私はPHPを学校の授業で少し触った程度で基本文法も知らない状態で参加しました。
![IMG_1220.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3241738/f8a4ce80-26f0-b1fa-0c27-d70526941d49.jpeg)


# 聞いた講演
### カンファレンスからはじめよ by びきニキ
https://fortee.jp/phpconkagawa-2024/proposal/a623e984-0c15-4c5c-9fb5-84049ff09b96

最初の講演はハックツハッカソンなどで少し接点のあったびきニキさんのを聞きました。
カンファレンスに参加するだけでなくその後の行動に繋げることを発信していました。
この記事を書くきっかけです。
また、他のカンファレンスに参加したいと感じました。

### 泥まみれの技術革新: あなたの[ PHPバージョンアップ | 新フレームワーク採用 | アーキテクチャ刷新 | … ]を後押しするために by nrslib
https://fortee.jp/phpconkagawa-2024/proposal/7f4622af-03b6-4b83-a0ef-e1cfc7b7c930

![IMG_1222.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3241738/13c9d04b-6c8c-9223-3025-da28c0451e25.jpeg)
ドメイン駆動設計入門を書いた人みたいな認識でしたが、話が面白く引き込まれました。
恐らく、このまま生きていけば必ず直面するであろう問題を成瀬さんの体験談をもとにわかりやすくまとめられていました。
まとめると、一晩でやればOKみたいな感じでした。

### 令和版ソフトウェアエンジニアの情報収集術 by Kanon
https://fortee.jp/phpconkagawa-2024/proposal/d9f74b93-9991-4932-afaf-ada75c330094

他の人の情報収集が気になったので聞きに行きました。
普通に私の情報収集がぬるいことに気付きました。
discordに参加して精進します、、

### ソースコードを美しくたもつために ～コードレビューの認知限界を突破し、年間400リリースを達成する～ by こたうち　さんさん
https://fortee.jp/phpconkagawa-2024/proposal/3944fedc-faa4-4a30-b3fb-4d6f560b905f

まだ、実際の実務を経験したことのない身としてはコードレビューってこうするのかと驚きました。
自社のコードもぐちゃぐちゃなのでLinterや静的解析の導入をしてみたいです。

### 1人プロ・ペアプロ・モブプロの効果的な使い分け by まきまき
https://fortee.jp/phpconkagawa-2024/proposal/db3e9634-4a79-46c1-84fd-8ffa4d495a13

ペアプロのメリットがきちんと理解できていなかったので目から鱗でした。
それぞれにメリット・デメリットが存在しているので場合に分けた使い分けを知ることが出来ました。
ハッカソンなどで使ってみたいです！

### PHPer のための Cloudflare 活用術 by 増永 玲
https://fortee.jp/phpconkagawa-2024/proposal/4cc166b7-3759-438f-a5af-6926720324bd

Cloudflareを雰囲気で理解していたのでとても勉強になりました。
エッジコンピューティングを分かりやすくするためにブラジルサーバーを使っていたのが印象的で面白かったです。
Cloudflareを触ってみようかと思いました。
あと、光おそ

### 地方こそサーバーレス、その意義に迫るサーバーレスPHP by 清家史郎
https://fortee.jp/phpconkagawa-2024/proposal/81c9a931-3413-42cf-bff0-21c0fd611cf7

クラウドを使う意義を確認できました。
また、サーバーレスアーキテクチャを再確認し、認識することが出来ました。

### 哲学史とモデリング 〜クラスはイデアだと思った? ざーんねんっ⭐︎エポケーでした〜 by 田中ひさてる
https://fortee.jp/phpconkagawa-2024/proposal/4ed7eece-47f7-4978-a8fd-452b29e0a234

いやー難しい
「哲学とプログラミング」異質の組み合わせかと思いきや意外と対応しているみたいなことを話していましたが、あんまり理解できてない気がします、
両方の知識が足りてない感じでした。
この話が理解できるくらいプログラミングを理解したいです。

# 最後に
初めてのカンファレンス楽しかった！
講演以外の無限うどんや企業ブースもよかったです。
![IMG_1217.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3241738/51dcf2fc-cc12-7ba0-3253-03c21c854dbe.jpeg)
美味しかった！

![IMG_8198.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3241738/57d83e78-5ac5-d59f-ef6e-ada564aee5e1.jpeg)
Apple Vision Pro をSTYLYさんのブースで初体験！
眼鏡が無かったのでぼやぼやしてたけどすごかったです。

他のカンファレンスにも参加したい！
プログラマーがハードウェアからソフトウェアまで体系的に理解し、キャッシュメモリの高速化の仕組みを深く理解するための学習ステップ

**はじめに**

キャッシュメモリの高速化メカニズムを理解するには、ハードウェアとソフトウェアの深い知識が必要です。しかし、ネット上で見かける情報は断片的で、体系的な理解を得るのが難しいと感じている方も多いでしょう。

そこで、**螺旋階段**のように段階的に学習を進め、ハードウェアとソフトウェアの基礎知識を固めながら、キャッシュメモリの本質に迫る学習ステップを提案します。

**1. ハードウェアの基礎固め**

まず、ハードウェアの土台となる以下のトピックを学びましょう。

* **コンピュータの構成要素**: CPU、メモリ、ストレージ、バスなど、コンピュータを構成する各要素の役割と機能を理解します。
* **論理回路**: 論理ゲート、真理表、コンビネーション回路、シーケンシャル回路などの基本的な論理回路を学び、デジタル回路の動作原理を理解します。
* **デジタルシステム**: クロック、タイミング、データ転送、エンコーディング/デコーディングなどのデジタルシステムにおける基本概念を習得します。

**2. CPUのしくみを知る**

次に、CPUの内部構造と動作原理を理解しましょう。

* **CPUアーキテクチャ**: レジスタ、命令セット、パイプライン、キャッシュメモリなど、CPUの主要な構成要素と役割を学びます。
* **命令実行**: 命令フェッチ、デコード、実行、結果書き込みなどの命令実行サイクルを理解し、CPUがどのようにプログラムを実行するかを学びます。
* **パフォーマンス指標**: クロック周波数、IPC、スループットなどの主要なパフォーマンス指標を理解し、CPUの性能を評価する方法を学びます。

**3. メモリ階層とキャッシュメモリ**

いよいよ、メモリ階層とキャッシュメモリの詳細な仕組みを学びます。

* **メモリ階層**: 主記憶、キャッシュメモリ、仮想記憶などのメモリ階層における各レベルの役割と特性を理解します。
* **キャッシュメモリの種類**: SRAM、DRAMなどのキャッシュメモリの種類とそれぞれの特徴を学びます。
* **キャッシュメモリ アクセスメカニズム**: キャッシュヒット、キャッシュミス、キャッシュ置換アルゴリズムなどのキャッシュメモリ アクセスメカニズムを理解し、キャッシュメモリがどのようにプログラム実行を高速化するのかを学びます。

**4. ソフトウェアとハードウェアの連携**

ソフトウェアがどのようにハードウェアと連携し、キャッシュメモリを活用するのかを学びましょう。

* **コンパイラ**: コンパイラが生成するコードとキャッシュメモリの関係を理解し、コンパイラ最適化がキャッシュ性能に与える影響を学びます。
* **オペレーティングシステム**: オペレーティングシステムがメモリ管理とキャッシュ管理を行う仕組みを理解し、OSがキャッシュ性能に与える影響を学びます。
* **パフォーマンス分析**: パフォーマンス分析ツールを使用して、プログラムのパフォーマンスボトルネックを特定し、キャッシュメモリの使用状況を分析する方法を学びます。

**5. 実践を通して理解を深める**

机上の学習だけでなく、実際に手を動かすことで理解を深めましょう。

* **アセンブリ言語プログラミング**: アセンブリ言語でプログラムを記述し、キャッシュメモリの使用状況を測定することで、キャッシュメモリへのアクセスがプログラム実行速度に与える影響を直接体験します。
* **キャッシュシミュレータ**: キャッシュシミュレータを使用して、さまざまなキャッシュ構成とアクセスメカニズムの影響をシミュレートし、キャッシュメモリの設計と実装に関する深い理解を得ることができます。
* **ハードウェアデバッガ**: ハードウェアデバッガを使用して、キャッシュメモリのアクセスをデバッグし、キャッシュミスが発生する原因を特定することができます。

**6. 螺旋階段のように学習を深める**

上記1〜5のステップを順番に学習するだけでなく、それぞれのトピックを繰り返し学び、関連する知識を繋ぎ合わせながら理解を深めていくことが重要です。

* **復習と再学習**: 理解が不十分だったトピックは、定期的に復習し、より深い理解を目指します。
* **関連知識の探索**: 各トピックを深く学ぶために、関連する書籍や論文、オンラインリソースなどを積極的に探索します。
* **実践と経験**: 学んだ知識を実際に試してみることで、理解を深め、新しい発見を得ることができます。
react-springの404ページが怖い

# react-springの404ページが怖い
![スクリーンショット 2024-05-13 9.32.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511372/6666732d-4f3f-c2ae-160b-051d0e021b0e.png)
![スクリーンショット 2024-05-13 9.32.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511372/97bb576a-7264-5e60-9c5b-00db72a21098.png)

なんの絵…？

そしてHomeをそのように略さないでほしかった💦
rex0220 項目書式プラグイン 曜日によるテーブル行の書式設定

[rex0220 項目書式プラグイン](https://qiita.com/rex0220/items/87470704fd4187e29406)で、曜日によるテーブル行の書式設定例です。

# 概要

[rex0220 項目書式プラグイン](https://qiita.com/rex0220/items/87470704fd4187e29406)で、テーブル行の曜日によってテーブル行の背景色を設定します。

テーブル行の日付と曜日は、[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、設定します。

![2024-05-13_09h12_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1932a20a-033c-7ec8-d80b-9ee9c034e3a4.png)

# 項目書式プラグイン設定

テーブルに条件と書式を指定すると、テーブル行単位に設定されます。

![2024-05-13_09h13_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1b8d8619-4baf-e1f2-3322-4f7b3556e011.png)

![2024-05-13_09h14_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/79632a11-0728-714b-83c0-e6cbbc12981f.png)

条件：曜日T が、"土" または "日" の場合に、書式を適用
IN(曜日T,"土","日")


# 計算式プラグイン

指定日付の月の日数で、テーブル行を作成し、日付と曜日を設定します。

![2024-05-13_09h18_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a75d2bdf-1242-2e5c-be34-c9a394cc099a.png)

```.js
OPTION: 循環参照を許可

// 日付 DATE (editable)
DATE_FORMAT(日付,"YYYY-MM-01")

// 曜日 SINGLE_LINE_TEXT
LET(w,ARRAY("日","月","火","水","木","金","土"),
ARRAY_GET(w,NVL(DATE_FORMAT(日付,"e"),7)))

// 日数 NUMBER
DATE_ENDOF(日付,"month","DD")

// テーブル SUBTABLE
日数

// テーブル.日付T DATE
IF(日付,DATE_ADD(日付,ROWNO(テーブル),"days"))

// テーブル.曜日T SINGLE_LINE_TEXT
LET(w,ARRAY("日","月","火","水","木","金","土"),
ARRAY_GET(w,NVL(DATE_FORMAT(日付T,"e"),7)))

```